How to create a key value array from two arrays - javascript

I have two arrays with the same number of elements which maps 1:1
const array1 = [1, 3, 2]
const array2 = [U2, U1, U3]
How can I generate a new array (or map) from array1 & array2 and have something like this ?
const result = [[1, U1], [2, U2], [3, U3]]

You can also use Array.forEach(). Before that you can sort the array1 array and then get the corresponding value from array2 prefixed with U to get the desired output:
const array1 = [1, 3, 2];
const array2 = ['U2', 'U1', 'U3'];
const result = [];
array1.sort(function(a,b){
return a-b;
})
array1.forEach((elem, index) => result.push([elem, array2[array2.indexOf('U'+elem)]]));
console.log(result);
If the prefix is not always U then this can be used:
const array1 = [1, 3, 2];
const array2 = ['U2', 'U1', 'U3'];
const result = [];
array1.sort(function(a,b){
return a-b;
})
array1.forEach((elem) => {
var array2Val = array2.find(val => val.indexOf(elem) !== -1);
result.push([elem, array2Val]);
});
console.log(result);

You could group the arrays by the numerical value of each item.
var array1 = [1, 3, 2],
array2 = ['U2', 'U1', 'U3'],
result = Object.values([array1, array2].reduce(
(o, a) => {
a.forEach(v => {
var k = v.toString().match(/\d+$/)[0];
(o[k] = o[k] || []).push(v);
});
return o;
},
Object.create(null)
));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to get a reduced array? My array is not getting returned

I am trying to get a reduced array.
My output is supposed to be [1,5,4] but it gives me an empty array.
let arr=[1,[2,3],4]
let newarr=[]
let myarr=()=>{
for(i=0;i<3;i++){
array=arr[i].reduce
newarr.push(array)
return newarr
}
}
You need to pass a function to your array.reduce,also you have to actually call your function,like so ( console.log calls it ):
const arr = [1, [2, 3], 4];
const myArr = (arr) => {
let newArray = [];
arr.forEach((arrayItem) => {
//we iterate every item in given array
if (Array.isArray(arrayItem)) {
//we check if item is actually an array to reduce
newArray.push(
arrayItem.reduce(function (previous, current) {
return previous + current;
})
); //if its an array then reduce it down to a single value using a reducer function and push it in new array
} else {
newArray.push(arrayItem); //otherwise just push it in new array as is
}
});
return newArray;
};
console.log( myArr(arr) );
there are always shorter and prettier ways to do the same,above solution is as readable as possible to understand it,an one-liner would be :
const arr = [1, [2, 3], 4]
const newArr = arr.map(i=>Array.isArray(i)?i.reduce((a,b)=>a+b):i)
console.log(newArr)
Array#reduce is an array method and it needs a function to be passed to it. Also you have defined a function but you do not invoke it.
Try the following:
let arr = [1, [2, 3], 4];
let newarr = [];
((array) => {
for(let i=0; i < array.length; i++) {
const el = array[i];
const topush = Array.isArray(el) ? el.reduce((total, curr) => total + curr, 0) : el;
newarr.push(topush)
}
})( arr );
console.log( newarr );
Alternatively, you can use Array#map and Array#reduce methods as follows. In both cases the trick is to identify the array so as to apply reduce to it:
const arr = [1, [2, 3], 4, [4, 5, 7]];
const newarr = arr.map(el =>
Array.isArray(el) ? el.reduce((sum,cur) => sum + cur,0) : el
);
console.log( newarr );

How to group by two array by index in javascript with es6 or lodash?

We have same two arrays to groupby theme by index.
Two arrays with same length and different value like blow.
How to groupby two array with their index by ES6 reduce or lodash?
array1 = [1,2,3,4] OR [{a:1},{b:2},{c:3},{d:4}]
array2 = [5,6,7,8] OR [{e:5},{f:6},{g:7},{h:8}]
finalArray = [[1,5],[2,6],[3,7],[4,8]]
I'm trying with different ways like group by with reduce in es6 or lodash concat but i can't find best solution for my problems.
Try this:
let array1 = [1, 2, 3, 4];
let array2 = [5, 6, 7, 8];
let res = array1.map((value, index) => {
return [value, array2[index]]
})
console.log(res);
If it is array of objects
let array1 = [{a:1},{b:2},{c:3},{d:4}];
let array2 = [{e:5},{f:6},{g:7},{h:8}];
let res = array1.map((value, index) => {
return [Object.values(value)[0],Object.values(array2[index])[0]]
})
console.log(res)
Use lodashes zip function
// _ is lodash
const array1 = [1,2,3,4]
const array2 = [5,6,7,8]
console.log(_.zip(array1, array2))
result
[ [ 1, 5 ], [ 2, 6 ], [ 3, 7 ], [ 4, 8 ] ]
If you are working with the array of objects. Get just the values using Object.values and grab the 0th element.
const array3 = [{a:1},{b:2},{c:3},{d:4}];
const array4 = [{e:5},{f:6},{g:7},{h:8}];
function firstval(ob){
return Object.values(ob)[0]
}
console.log(_.zip(array3.map(firstval), array4.map(firstval)))
You can also write your own zip. This is a limited version. That handles only 2 elements, doesn't accept or return generators etc.
It could easily be extended to take a spread operator and therefore any number of arguments. You don't seem to need that level of flexibility though.
function zip(a, b) {
const num = Math.min(a.length, b.length);
const result = [];
for(i = 0; i < num; i++) result.push([a[i], b[i]]);
return result;
}
Following code works under these assumptions:
all input arrays have same length
if array element is object, it has only one property
function getValue(element) {
if (typeof element === 'object') {
return Object.values(element).pop()
} else {
return element
}
}
function zipArrays(arr1, arr2) {
return arr1.reduce((acc, elm1, index) => {
const elm2 = arr2[index]
const elm = [getValue(elm1), getValue(elm2)]
acc.push(elm)
return acc
}, [])
}
// usage:
const array1 = [1,2,3,4] // OR [{a:1},{b:2},{c:3},{d:4}]
const array2 = [5,6,7,8] // OR [{e:5},{f:6},{g:7},{h:8}]
const finalArray = zipArrays(array1, array2)

Can we use one Array.filter() method over several arrays?

I am currently filtering three arrays to return only the iterations that match the paratemer, something like:
filterMyArrays(parameter) {
this.array1 = this.array1.filter(e => (e.item === parameter));
this.array2 = this.array1.filter(e => (e.item === parameter));
this.array3 = this.array1.filter(e => (e.item === parameter));
}
where all three arrays are based off the same original data return.
The code above (well, pseudocode, but you get the idea) is working as expected, but I was wondering if there is a method to create one single array.filter() instance that I can then invoke over several arrays, so my code becomes a bit cleaner and less repetitive. Something like, perhaps:
const myArrays = [array1, array2, array3]
myArrays.filter(e => (e.item === parameter));
or something like
let filterMySelection(desiredArray) = desiredArray.filter(e => (e.item === parameter));
array1 = filterMySelection(array1);
I have fiddled around with both attempts, but none of them worked.
you can use map along with filter as follows:
const combined_arrays = [array_1, array_2, array_3];
let result = combined_arrays.map(function(arr) {
return [arr.filter(e => (e.item == parameter))];
});
const myArrays = [array1, array2, array3];
const filteredArrays = myArrays.map(
array => array.filter(e => e.item === parameter)
);
// OR
let filterMySelection = (desiredArray) => desiredArray.filter(
e => e.item === parameter
);
const array1 = filterMySelection(array1);
var array = [1, 3, 6, 8, 11];
var array2 = [4, 2, 5, 6, 15];
var array3 = [7, 4, 2, 6, 14];
var a = []
a.push(array)
a.push(array2)
a.push(array3)
// OR
// a.push([1, 3, 6, 8, 11])
// a.push([4, 2, 5, 6, 15])
// a.push([7, 4, 2, 6, 14])
a.forEach((array, index) => a[index] = array.filter(function(number) { return number > 7; }))
var lucky = array.filter(function(number) {
return number > 7;
});
console.log(a);
You can try something like this:
Idea:
Save reference of all necessary array in another array.
Loop on it using .map and return filtered list.
Inside each iteration, filter current array and return result.
Override necessary on this with filtered values
var arrs = [ this.array1, this.array2, this.array3 ];
var [ array1, array2, array3 ] = arrs.map((arr) => arr.filter((e) => e.item === parameter ));
Object.assign(this, { array1, array2, array3 });
You can also save filter function in a variable and use it in all filters:
filterMyArrays(parameter) {
const filterFn = (e) => (e.item === parameter)
this.array1 = this.array1.filter(filterFn);
this.array2 = this.array1.filter(filterFn);
this.array3 = this.array1.filter(filterFn);
}
You can use a mixture of map and filter.
const myArrays = [array1, array2, array3];
let newArray = myArrays.map(k => k.filter(e => e.item === parameter));

Arrays withing an array: how to push all elements forward by one with javascript

This is my array of arrays:
arr_1 = [1,2,3]
arr_2 = [4,5,6]
arr_3 = [7,8,9]
arr = [arr_1, arr_2, arr_3]
arr = [[1,2,3], [4,5,6], [7,8,9]]
What I want to do is push all elements like so that the final array is like the following and insert another element at the beginning of my array:
arr = [[i,1,2], [3,4,5], [6,7,8], [9]]
All sub-arrays must not be more than 3 elements.
Thanks for your help.
You could visit all inner arrays and unshift the leftover values from the previous loop.
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
chunk = 3,
item = 'x',
i = 0,
temp = [item];
while (i < array.length) {
array[i].unshift(...temp);
temp = array[i].splice(chunk, array[i].length - chunk);
i++;
}
if (temp.length) {
array.push(temp);
}
console.log(array.map(a => a.join(' ')));
You can use the function reduce
var arr = [[1,2,3], [4,5,6], [7,8,9]],
newElem = "newOne",
all = [newElem, ...arr.reduce((a, c) => [...a, ...c], [])], // All together
// Build the desired output asking for the result of:
// element mod 3 === 0
result = all.reduce((a, c, i) => {
if (i % 3 === 0) a.push([c]);
else a[a.length - 1].push(c);
return a;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could move on each iteration last element from previous array to next one and if the last sub-array has more then 3 elements then remove the last one and add it to new array.
let arr_1 = [1, 2, 3],
arr_2 = [4, 5, 6],
arr_3 = [7, 8, 9],
arr = [arr_1, arr_2, arr_3]
setInterval(function() {
const last = arr.length - 1;
const newElement = parseInt(Math.random() * 30)
arr.forEach((a, i) => {
if(i == 0) a.unshift(newElement);
if(arr[i + 1]) arr[i + 1].unshift(a.pop())
else if(arr[last].length > 3) arr[last + 1] = [arr[last].pop()]
})
console.log(JSON.stringify(arr))
}, 1000)
You can do this quite succinctly with a simple unravel/ravel. It easy to adjust group size too.
let arr = [ [1,2,3], [4,5,6], [7,8,9]]
let newEl = 0
let groupSize = 3
var newArr = [];
var unravelled = arr.reduce((a, c) => a.concat(c), [newEl])
while(unravelled.length) newArr.push(unravelled.splice(0,groupSize));
console.log(newArr)
arr_1 = [1, 2, 3]
arr_2 = [4, 5, 6]
arr_3 = [7, 8, 9]
arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
function reassignChunk(x) {
// create an array which will be used to store unwrapped values
var newArray = [];
arr.forEach(function(elem) {
newArray.push(...elem); //using spread operator to unwrap values
});
newArray.unshift(x, limit)
var modArray = [];
var m, j, temparray, chunk = 3;
for (m = 0; m < newArray.length; m = m + limit) {
// creatinging new array using slice
modArray.push(newArray.slice(m, m + limit));
}
console.log(modArray)
}
reassignChunk(13, 3)
arr = [[i,1,2], [3,4,5], [6,7,8], [9]]
Assuming all your elements are numbers, you can do it like this:
Prepend i to the array
Flatten the array
Convert the array to a comma-separated string
Split the string into chunks of at most 3 numeric substrings (2 commas)
Convert the chunks back into arrays of numbers
const arr_1 = [1,2,3];
const arr_2 = [4,5,6];
const arr_3 = [7,8,9];
const i = 42;
const result = [i,...arr_1,...arr_2,...arr_3].join()
.match(/(?:[^,]+(,|$)){1,2}[^,]*/g).map( x => x.split(',').map(Number) )
;
console.log( result );
You may do your 2d unshifting simply as follows;
var arr_1 = [1,2,3],
arr_2 = [4,5,6],
arr_3 = [7,8,9],
arr = [arr_1, arr_2, arr_3],
us2d = (a2d,...is) => is.concat(...a2d)
.reduce((r,e,i) => (i%3 ? r[r.length-1].push(e)
: r.push([e]), r), []);
console.log(JSON.stringify(us2d(arr,0)));
console.log(JSON.stringify(us2d(arr,-2,-1,0)));

How to only allow an array to be pushed into an array once?

I have an array that has other arrays in it which have been pushed in. For an example:
const Arrays = [ [1,2,3], [4,5,6], [7,8,9], [2,1,3] ];
let myArr = [];
Arrays.map(arr => {
if(myArr.indexOf(arr)){
return
}
myArr.push(arr)
})
const myArr = [ [1,2,3], [4,5,6], [7,8,9], [2,1,3] ];
In this array you can see that there are two arrays with the same set of numbers 1, 2 and 3. I want to somehow set a condition saying:
If this array already exist then do not add this array in any order again to prevent this from happening. So that when it comes in the loop that this set of numbers comes up again it will just skip over it.
You can use some() and every() methods to check if same array already exists before push().
const myArr = [ [1,2,3], [4,5,6], [7,8,9] ];
let input = [2,1,3]
function check(oldArr, newArr) {
return oldArr.some(a => {
return a.length == newArr.length &&
a.every(e => newArr.includes(e))
})
}
if(!check(myArr, input)) myArr.push(input)
console.log(myArr)
You can make temp array with sorted element with joined and check by indexOf
const myArr = [ [1,2,3], [4,5,6], [7,8,9], [2,1,3],[6,5,4] ];
var newArr = [];
var temp = [];
for(let i in myArr){
let t = myArr[i].sort().join(",");
if(temp.indexOf(t) == -1){
temp.push(t);
newArr.push(myArr[i]);
}
}
console.log(newArr);
The accepted answer does not respect the special case where only two values are in the array and the array has to check against two values in a different count like
[1, 1, 2]
and
[1, 2, 2]
which are different arrays.
For a working solution, I suggest to use a Map and count the occurences of same values of the first array and subtract the count of the values for the other arrray.
As result return the check if all elements of the Map are zero.
function compare(a, b) {
var map = new Map;
a.forEach(v => map.set(v, (map.get(v) || 0) + 1));
b.forEach(v => map.set(v, (map.get(v) || 0) - 1));
return [...map.values()].every(v => !v);
}
var array = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [2, 1, 3], [1, 1, 2], [1, 2, 2], [2, 1, 1], [2, 1, 2]],
unique = array.reduce((r, a) => (r.some(b => compare(a, b)) || r.push(a), r), []);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One way is to sort them numerically with .sort() then compare them.

Categories

Resources