Reduce multidimensional with string and numbers array in Javascript - javascript

I have some idea of how reduce works, but I'm having problem with a multidimensional array. How can I reduce this:
y = [['x', 0.5], ['x', 0.5], ['z', 2], ['z', 2]];
into this:
y = [['x', 1], ['z', 4]];
Thanks!

You could reduce with an accumulated object that store sum of key, then use Object.entries() to transform it back to an array of array
const y = [
["x", 0.5],
["x", 0.5],
["z", 2],
["z", 2],
]
const res = Object.entries(
y.reduce((acc, [key, value]) => {
acc[key] = (acc[key] || 0) + value
return acc
}, {})
)
console.log(res)

Related

Convert a nested array in to a nested object in javascript

I want to write a code in javascript to convert a nested array in to a nested object. The point is every single elements in the nested array would be an array itself, so should convert to a nested object:
Examples:
[['a', 1], ['b', 2], ['c', [['d', 4]]]] => { a: 1, b: 2, c: { d: 4 } }
[['a', 1], ['b', 2], ['c', [['d', [['e', 5], ['f', 6]]]]]]
=> { a: 1, b: 2, c: { d: { e: 5, f: 6 } } }
I tried to go with this concept:
define a function to iterate over the base array. for every single element, it will make a key:value for the object. if the value is an array, the function will call itself.
but Actually I dont know how to write it.
const nestedArrayToObject = function (arr) {
let obj = {};
for (let i = 0; i < arr.length; i++) {
let key = arr[i][0];
let val = arr[i][1];
if (!Array.isArray(val)) {
obj[key] = val;
} else {
nestedArrayToObject(val); ???
}
}
return obj;
};
You can use Object.fromEntries to convert an array of key-value pairs to an object. For each value that is also an array, recursively call the conversion function.
function convert(arr) {
return Object.fromEntries(arr.map(([k, v]) =>
[k, Array.isArray(v) ? convert(v) : v]));
}
console.log(convert([['a', 1], ['b', 2], ['c', [['d', 4]]]]));
console.log(convert([['a', 1], ['b', 2], ['c', [['d', [['e', 5], ['f', 6]]]]]]));

How to group two-dimensional array by value at zero index

Let's say I have the following two-dimensional array:
const array = [[1, 1], [1, 2], [2, 1], [2, 2]];
What I want to do is to find all the values under first index which have common zero index value. So the result should be the following:
[[1, [1, 2]], [2, [1, 2]]]
Or maybe Map would look better:
[Map(1 => [1, 2]), Map(2 => [1, 2])]
How can I do that? With or without lodash. My solution looks a bit bloated and messy:
const array = [[1, 1], [1, 2], [2, 1], [2, 2]];
const grouppedCartItemsMap = new Map();
array.forEach((item) => {
const [locationId, contractId] = item;
if (!grouppedCartItemsMap.has(locationId)) {
grouppedCartItemsMap.set(locationId, [contractId]);
} else {
const existingItem = grouppedCartItemsMap.get(locationId);
if (!existingItem.includes(contractId)) {
grouppedCartItemsMap.set(locationId, [...existingItem, contractId]);
}
}
});
console.log(grouppedCartItemsMap);
If an object would work:
const array = [[1, 1], [1, 2], [2, 1], [2, 2]];
const grouped = {};
for (const [first, last] of array) {
grouped[first] ??= [];
grouped[first].push(last);
}
console.log(grouped);
This looks like a use case for reduce:
const array = [[1, 1], [1, 2], [2, 1], [2, 2]];
const grouppedCartItemsMap = array.reduce((acc, [locationId, contractId]) => {
if (!acc.has(locationId)) acc.set(locationId, [contractId]);
else acc.get(locationId).push(contractId);
return acc;
}, new Map());
console.log([...grouppedCartItemsMap.entries()]);

How to join two 2D array JavaScript

I have two 2D array and what to merge row VS row.
arr1 = [[a,b,c],[d,e,f],[g,h,i]]
arr2 = [[1,2,3],[4,5,6],[7,8,9]]
I want to have output like this
arr2 = [[a,b,c,1,2,3],[d,e,f,4,5,6],[g,h,i,7,8,9]]
How do I do this with map method?
const arr1 = [
['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i'],
];
const arr2 = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const result = arr1.map((arr1Item, i) => [...arr1Item, ...arr2[i]]);
console.log(result);
You can use concat with map:
var arr1 = [['a','b','c'],['d','e','f'],['g','h','i']];
var arr2 = [[1,2,3],[4,5,6],[7,8,9]];
var result = arr1.map((k,i)=>k.concat(arr2[i]));
console.log(result);
you could use map, map and push like so...
const foo = [
['a','b','c'],
['d','e','f'],
['g','h','i']
]
const bar = [
[1,2,3],
[4,5,6],
[7,8,9]
]
foo.map((el, i) => {
el.map((e) => {
bar[i].push(e)
})
})
console.log(bar)

.some() function not working with nested arrays?

For example, if I want to check whether arr1 (an array of 3 arrays) contains any element of arr2 (an array of 2 arrays), I use the .some() function, but it returns false.
let arr1 = [[1, 2], [2, 3], [3, 4]]
let arr2 = [[1, 2], [5, 2],]
if (arr1.some(x => arr2.includes(x))) {
alert('arr1 has arr2')
};
x does return the array [1, 2], but for some reason it doesn't pass the check for .some() in arr1.
.includes will return true if the passed item is === to one in the array, but separate objects are never === to each other in JS unless one was created from a reference from the other:
const arr = [1, 2];
console.log(arr === [1, 2]);
const arr2 = arr; // same reference
console.log(arr === arr2);
. I suppose one method would be to stringify the subarrays first:
let arr1 = [[1, 2], [2, 3], [3, 4]]
let arr2 = [[1, 2], [5, 2],]
if (arr1.some((subarr1) => {
const str1 = JSON.stringify(subarr1);
return arr2.some(subarr2 => JSON.stringify(subarr2) === str1);
})) {
console.log('arr1 has arr2')
}
I think includes function isn't working for arrays 2 dimension
Please change code like this
let arr1 = [[1, 2], [2, 3], [3, 4]]
let arr2 = [[1, 2], [5, 2],]
if (arr1.some(x => {
return arr2.some(item => item.toString() === x.toString())
})) {
alert('arr1 has arr2')
};
You can you _.isEqualof lodash to compare the Array.
let arr1 = [[1, 2], [2, 3], [3, 4]]
let arr2 = [[1, 2], [5, 2]]
if (arr1.some(x => {
return arr2.some(item => _.isEqual(item, x))
})) {
console.log('arr1 has arr2')
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

How can I use reduce to calculate the intersection of multiple arrays?

Example:
myArray = [[1,2,3,4],
[2,3,4,5],
[3,4,5,6]
];
Expected output:
newArray = [3,4]
How do I generate a new array with the values present in all 3 arrays?
While reducing, return an intersection of the accumulator with the current sub-array being iterated over:
const myArray = [[1,2,3,4], [2,3,4,5], [3,4,5,6]];
const intersection = myArray.reduce((a, arr) => (
a.filter(num => arr.includes(num))
));
console.log(intersection);
You can use .filter() to extract the matching values:
let myArray = [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6]];
let intersect = ([f, ...r]) => f.filter(v => r.every(a => a.includes(v)));
console.log(intersect(myArray));

Categories