Related
When I have this array with this data structure:
[[3, 16, 1]
[3, 17, 1]
[3, 18, 1]
[3, 19, 1]
[3, 20, 1]
[3, 19, 1]
[3, 21, 1]
[3, 23, 1]
[3, 16, 1]
[3, 17, 1]
[2, 24, 1]
[2, 25, 1]
[2, 26, 1]
[2, 24, 1]]
and I want to count array elements and multiply this to the last number of the array, like this:
[[3, 16, 2]
[3, 17, 2]
[3, 18, 1]
[3, 19, 2]
[3, 20, 1]
[3, 21, 1]
[3, 23, 1]
[2, 24, 2]
[2, 25, 1]
[2, 26, 1]]
I tried to do it with:
array.forEach(function(x) {
counts[x] = (counts[x] || 0)+1;
});
but this changes the data structure, is there another form to do it?
I rewrite your function and console.log the output you want.
Whenever I check a new array, I store it in checkedArr and will check against it to prevent duplicate records.
const arr = [
[3, 16, 1],
[3, 17, 1],
[3, 18, 1],
[3, 19, 1],
[3, 20, 1],
[3, 19, 1],
[3, 21, 1],
[3, 23, 1],
[3, 16, 1],
[3, 17, 1],
[2, 24, 1],
[2, 25, 1],
[2, 26, 1],
[2, 24, 1],
];
const checkedArr = [];
const output = [];
for (let i = 0; i < arr.length; i++) {
let count = 0;
if (!isArrayChecked(arr[i])) {
checkedArr.push(arr[i]);
for (let j = i; j < arr.length; j++) {
if (isArraySame(arr[i], arr[j])) {
count++;
}
}
output.push([arr[i][0], arr[i][1], count]);
}
}
function isArrayChecked(array) {
let exist = false;
for (let k = 0; k < checkedArr.length; k++) {
if (isArraySame(array, checkedArr[k])) {
exist = true;
break;
}
}
return exist;
}
function isArraySame(arr1, arr2) {
if (arr1[0] !== arr2[0] || arr1[1] !== arr2[1] || arr1[2] !== arr2[2])
return false;
return true;
}
console.log(output);
The problem with your code is in counts[x]. You can't use an array to index an object.
You can solve the issue by stringifying the array. That is, use:
counts[String(x)] = (counts[String(x)] || 0)+1;
let arr=[
[3, 16, 1],
[3, 17, 1],
[3, 18, 1],
[3,16,1],
[3, 19, 1],
[3, 20, 1],
[3, 19, 1],
[3, 21, 1],
[3, 23, 1],
[3, 16, 1],
[3, 17, 1],
[2, 24, 1],
[2, 25, 1],
[2, 26, 1],
[2, 24, 1]]
let solution = (arr) => {
let obj = {};
let result = [];
for (let i of arr) {
let keyOfObj = JSON.stringify(i);
obj[keyOfObj] ? obj[keyOfObj]++ : obj[keyOfObj] = 1;
}
for (let [key, value] of Object.entries(obj)) {
let objKeyArr = JSON.parse(key);
if (value >= 2) {
let lastElemt = objKeyArr[objKeyArr.length - 1];
objKeyArr.splice(objKeyArr.length - 1, 1, lastElemt * value);
result.push(objKeyArr);
} else {
result.push(objKeyArr);
}
}
return result;
};
solution(arr)
I have a table like this:
The colored blocks have coordinates as an array:
[
[1, 1],
[2, 1],
[2, 4],
[2, 5],
[3, 2],
[3, 4],
[4, 4],
[4, 5],
[4, 6],
[4, 7],
[5, 3],
[6, 3],
[6, 4],
[6, 5]
]
Now I want to group the neighboring blocks (horizontal and vertical) to independent child array.
The output estimated is like:
[
[
[1, 1],
[2, 1]
],
[
[2, 4],
[2, 5],
[3, 4],
[4, 4],
[4, 5],
[4, 6],
[4, 7]
],
[
[3, 2]
],
[
[5, 3],
[6, 3],
[6, 4],
[6, 5]
]
]
How to use a function to do this?
Edit: I tried to iterate each value in the input array and compare to [1, 1], if one of the coordinate is the same, push them to an new array and delete in the input array, and use recursion to do this again. But I stuck by a problem...as I should group [2, 5] and [4, 5] but cannot group [4, 4] and [6, 4]
You could filter the grouped items and build a new group with the own indices.
const
data = [[1, 1], [2, 1], [2, 4], [2, 5], [3, 2], [3, 4], [4, 4], [4, 5], [4, 6], [4, 7], [5, 3], [6, 3], [6, 4], [6, 5]],
offsets = [[-1, 0], [1, 0], [0, -1], [0, 1]],
groups = data.reduce((r, [i, j]) => {
const
own = [];
temp = r.filter(group => {
const found = group.some(g => offsets.some(o => i + o[0] === g[0] && j + o[1] === g[1]));
if (!found) return true;
own.push(...group);
});
return [...temp, [...own, [i, j]]];
}, []);
console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }
It seems to me that you are having just a logic problem, not a JavaScript, since you know how to nest the array, is just having a problem to find the right logic to group neighbors.
You can't just compare one part of the coordinate, since the other can me really distant. You need to compare both. If you want to find the neighbor coordinate you need to have one part of the coordinate equal and the another part exactly with 1 distance away.
var arr =
[
[1, 1],
[2, 1],
[2, 4],
[2, 5],
[3, 2],
[3, 4],
[4, 4],
[4, 5],
[4, 6],
[4, 7],
[5, 3],
[6, 3],
[6, 4],
[6, 5]
];
var groupedArr = new Array();
for(i = 0; i < arr.length; i++)
{
var grouped = false;
for(j = 0; j < groupedArr.length; j++)
{
for(k = 0; k < groupedArr[j].length; k++)
{
if((arr[i][0] == groupedArr[j][k][0] && Math.abs(arr[i][1] - groupedArr[j][k][1]) == 1)
|| (arr[i][1] == groupedArr[j][k][1] && Math.abs(arr[i][0] - groupedArr[j][k][0]) == 1))
{
groupedArr[j].push(arr[i]);
grouped = true;
break;
}
}
if(grouped)
break;
}
if(!grouped)
{
var newGroup = new Array();
newGroup.push(arr[i]);
groupedArr.push(newGroup);
}
}
console.log(groupedArr);
looks like clustering problem. But we can solve with this simple code for small data.
ax = [[1, 1], [2, 1], [2, 4], [2, 5], [3, 2], [3, 4], [4, 4], [4, 5], [4, 6], [4, 7], [5, 3], [6, 3], [6, 4], [6, 5]];
console.log(JSON.stringify(reForm(ax)));
function reForm(a) {
const ret = [];
while (a.length > 0) {
var sub = [a.shift()];
var i=0;
while (i<sub.length){
var j=0
while(j<a.length){
if((a[j][0]==sub[i][0] && Math.abs(a[j][1]-sub[i][1])==1) ||
(a[j][1]==sub[i][1] && Math.abs(a[j][0]-sub[i][0])==1))
sub.push(...a.splice(j,1));
else j++
}
i++;
}
ret.push(sub);
}
return ret;
}
You can do this by using recursion
var array =[
[1, 1],
[2, 1],
[2, 4],
[2, 5],
[3, 2],
[3, 4],
[4, 4],
[4, 5],
[4, 6],
[4, 7],
[5, 3],
[6, 3],
[6, 4],
[6, 5]
]
var returnval = new Array();
while(array.length>0)
{
var temp = new Array();
var item = array[0];
array.splice(0, 1);
temp.push(item);
findnext(item,temp);
returnval.push(temp);
}
console.log(returnval);
function findnext(item, temp)
{
for(var i=0;i<array.length;i++)
{
if((array[i][0]==item[0] && Math.abs(array[i][1]-item[1])==1) || (array[i][1]==item[1] && Math.abs(array[i][0]-item[0])==1))
{
temp.push(array[i]);
item1 = array[i];
array.splice(i,1);
findnext(item1, temp);
}
}
}
how can I do Looping Through to iterate each item console.log,
I want to iterate only for a loop way
this is the array
let array = [
[1,2,3],
[4,5,6],
[7,8,9],
[[10,11,12],13,14],
[[15,16,16],[17,18,[19,20]]]
];
You would need a nested loop. JavaScript has different ways to do this. Here's an example following Functional Programming:
array.forEach(function (outer) {
outer.forEach(function (inner) {
console.log(inner)
})
});
Since you have a deeply nested array, you might also want to flat it first.
Get a flat array and iterate for an ouput.
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [[10, 11, 12], 13, 14], [[15, 16, 16], [17, 18, [19, 20]]]];
array
.flat(Infinity)
.forEach(v => console.log(v));
A more classic approach with a recursive callback.
const show = v => {
if (Array.isArray(v)) v.forEach(show);
else console.log(v);
};
let array = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [[10, 11, 12], 13, 14], [[15, 16, 16], [17, 18, [19, 20]]]];
array.forEach(show);
You can try something like this?
This function should console log every item in the array and all sub-arrays.
// using Array.forEach
const recursiveLoop1 = (elem) => {
if (Array.isArray(elem)) {
elem.forEach((innerElem) => {
recursiveLoop1(innerElem)
})
} else {
console.log(elem)
}
}
// using classic for-loop
const recursiveLoop2 = (elem) => {
if (Array.isArray(elem)) {
for (let i = 0; i < elem.length; i++) {
recursiveLoop2(elem[i])
}
} else {
console.log(elem)
}
}
let array = [
[1,2,3],
[4,5,6],
[7,8,9],
[[10,11,12],13,14],
[[15,16,16],[17,18,[19,20]]]
];
recursiveLoop1(array);
recursiveLoop2(array);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have multiple arrays in a main/parent array like this:
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
I have the code to select the arrays that are repeated 3 or more times (> 3) and assign it to a variable.
The code is:
var arr = [[1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12]]
arr.sort((a, b) => a[0] - b[0] || a[1] - b[1])
// define equal for array
const equal = (arr1, arr2) => arr1.every((n, j) => n === arr2[j])
let GROUP_SIZE = 3
first = 0, last = 1, res = []
while(last < arr.length){
if (equal(arr[first], arr[last])) last++
else {
if (last - first >= GROUP_SIZE) res.push(arr[first])
first = last
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first])
console.log(res)
So the final result is:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12]]
My problem: But the problem is, I have an array like this {from: [12, 0], to: [14, 30]}.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{from: [12, 0], to: [14, 5]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
{from: [12, 0], to: [14, 5]},
{from: [4, 30], to: [8, 20]},
[2, 12],
[2, 12]
];
When I try to use the above code, it doesn't work. The error message is:
Uncaught TypeError: arr1.every is not a function
The final result should be:
console.log(repeatedArrays);
>>> [[1, 17], [2, 12], {from: [12, 0], to: [14, 5]}]
How can I make that code above work?
If you introduce a non array into the mix, you need to handle it differently.
Yours already work with array so I'm adding object style check for both sort and equal.
var arr = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
{ from: [4, 30], to: [8, 21] },
{ from: [12, 0], to: [14, 5] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
{ from: [12, 0], to: [14, 5] },
{ from: [4, 30], to: [8, 20] },
[2, 12],
[2, 12]
];
arr.sort((a, b) => {
if (a instanceof Array && b instanceof Array) {
return a[0] - b[0] || a[1] - b[1]
} else if (a instanceof Array || b instanceof Array) {
return a instanceof Array ? -1 : 1
} else {
return a.from[0] - b.from[0] || a.from[1] - b.from[1] || a.to[0] - b.to[0] || a.to[1] - b.to[1]
}
});
// define equal for array
const equal = (arr1, arr2) => {
if (arr1 instanceof Array) {
return arr1.every((n, j) => n === arr2[j]);
} else {
if (arr2 instanceof Array) return false;
for (let k in arr1) {
if (!arr1[k].every((n, j) => n === arr2[k][j])) {
return false
}
}
return true;
}
};
let GROUP_SIZE = 3;
(first = 0), (last = 1), (res = []);
while (last < arr.length) {
if (equal(arr[first], arr[last])) last++;
else {
if (last - first >= GROUP_SIZE) res.push(arr[first]);
first = last;
}
}
if (last - first >= GROUP_SIZE) res.push(arr[first]);
console.log(res);
You can use the function reduce for grouping and counting the objects and then execute the function filter for getting the object with count >= 3.
var array = [ [1, 17], [1, 17], [1, 17], [2, 12], [5, 9], [2, 12], [6, 2], [2, 12], [2, 12] ];
let result = Object.values(array.reduce((a, [c, b]) => {
let key = `${c}|${b}`;
(a[key] || (a[key] = {count: 0, value: [c, b]})).count++;
return a;
}, {})).filter(o => {
if (o.count >= 3) {
delete o.count;
return true;
}
return false;
}).map(({value}) => value);
console.log(result);
.as-console-wrapper { min-height: 100%; }
Really simple - filter it all, then remove duplicates with Set and JSON methods (because it's nested arrays not objects):
var array = [
[1, 17],
[1, 17],
[1, 17],
[2, 12],
[5, 9],
[2, 12],
[6, 2],
[2, 12],
[2, 12]
];
var repeatedArrays = [...new Set(array.filter(e => array.filter(f => JSON.stringify(e.sort()) == JSON.stringify(f.sort()))).map(JSON.stringify))].map(JSON.parse);
console.log(repeatedArrays);
I am facing an issue with the java-script multidimensional array . I want to search a date and month in a given array if present .I mean i want to count dates except saturday and sunday and national holidays I have this array
var natDays = [
[1, 1, 'uk'],
[1, 19, 'uk'],
[2, 16, 'uk'],
[4, 23, 'uk'],
[7, 03, 'uk'],
[7, 04, 'uk'],
[9, 07, 'uk'],
[8, 12, 'uk'],
[11, 11, 'uk'],
[11, 26, 'uk'],
[12, 25, 'uk']
];
from reference of this answer Here . I have created my function like this
function check_hol(month,date)
{
var natDays = [
[1, 1, 'uk'],
[1, 19, 'uk'],
[2, 16, 'uk'],
[4, 23, 'uk'],
[7, 03, 'uk'],
[7, 04, 'uk'],
[9, 07, 'uk'],
[8, 12, 'uk'],
[11, 11, 'uk'],
[11, 26, 'uk'],
[12, 25, 'uk']
];
for( var md = 0; md <= natDays.length; md++ )
{
alert(natDays[md][0]+'='+month+' and '+natDays[md][1]+'='+date) ;
if( natDays[md][0] != month && natDays[md][1] != date )
{
return true;
}
}
return false;
}
I am using this function to calculate the working days in this function
function workingDays(){
var n=0;
for(var i=1; i<=dp.datediff; i++){
var d1 = new Date();
d1.setDate(d1.getDate()+i);
if(d1.getDay() !== 0&&d1.getDay()!==6 && check_hol(d1.getMonth()+1,d1.getDate())===true)
{
n++;
}
}
alert(n);
dp.wdiff = n;
getShipDays();
getProdDays();
getQuantity();
getShipProdDays();
}
but it returns 0 in the output of working days . if i remove && check_hol(d1.getMonth()+1,d1.getDate())===true from my second function it is working fine .
can't understand where i am wrong .
Instead of != the code should make use of == because you want to match when the value is found. If you do this it will search in entire array for the value.
And instead of <= in for should be < because your index start from 0.
for (var md = 0; md < natDays.length; md++) { // changed in md < natDays
if (natDays[md][0] == month && natDays[md][1] == date) { // if values are == that means the value is found
return true; // isHoliday
}
}
function check_hol(month, date) {
var natDays = [
[1, 1, 'uk'],
[1, 19, 'uk'],
[2, 16, 'uk'],
[4, 23, 'uk'],
[7, 03, 'uk'],
[7, 04, 'uk'],
[9, 07, 'uk'],
[8, 12, 'uk'],
[11, 11, 'uk'],
[11, 26, 'uk'],
[12, 25, 'uk']
];
for (var md = 0; md < natDays.length; md++) { // changed in md < natDays
if (natDays[md][0] == month && natDays[md][1] == date) { // if values are == that means the value is found
return true; // isHoliday
}
}
return false; // !isHoliday => isWorkingDay
}
alert("found: " + check_hol(11,11));
alert("found: " + check_hol(11,12));
You need to make some changes in working days because, if the value was found (true) means that is holiday.
if(d1.getDay() !== 0&&d1.getDay()!==6 && !check_hol(d1.getMonth()+1,d1.getDate()))