The problem I have is, that I want to combine a 2D Array like this:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 32, 12, … ],
[ "Mercedes", 24, 21, … ],
[ "Toro Rosso", 7, 8, … ]
]
So in this example I have the String "Mercedes" twice at index 0 in the arrays.
What I want the output to be is the following:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 56, 33, … ],
[ "Toro Rosso", 7, 8, … ]
]
So if a String like "Mercedes" is appearing twice in that array I want the second one to be deleted. But the values from the second array must be taken over into the first "Mercedes" Array.
It seems that you actually want to aggregate similar values in the array. Therefore you could do a cycle in foreach and save yourself in a temporary array the string values already known and instead in another your merged classes. At that point, as you scroll through your array, you can check if you have already added an equal string in the first fake, and if so, you can take its index and aggregate them correctly in the other array.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
var tmp1 = [], tmp2 = [];
arr.forEach(function(currentValue, index, arr) {
// currentValue contain your element
// index contain the index of your element
// arr contain you entire "values" array
var ind = tmp1.indexOf(currentValue[0]);
if(ind === -1) {
tmp1.push(currentValue[0]);
tmp2.push(currentValue);
} else {
tmp2[ind][1] += currentValue[1];
tmp2[ind][2] += currentValue[2];
}
});
console.log(tmp2);
You can use reduce() to build a object and then use Object.values()
const arr = [
[ "Renault", 61, 16 ],
[ "Ferrari", 58, 10],
[ "Mercedes", 32, 12],
[ "Mercedes", 24, 21],
[ "Toro Rosso", 7, 8]
]
let res = arr.reduce((ac, [k, ...rest]) => {
if(!ac[k]) ac[k] = [];
ac[k] = ac[k].concat(k,...rest);
return ac;
},[])
console.log(Object.values(res))
Sure, by creating an array for your names and then separate the unique ones from them, at last, match them with the index.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
let c = [...new Set(arr.map(a => a[0]))] // get unique values of all arr[0]
let ans = arr.filter((a, post) => {
if (c[post]) { // check if index exists because we seperated one, the last is undefined here
if (a[0] == c[post]) {
return a;
}
} else {
return a; // else return as usual
}
})
console.log(ans)
You get the filtered array.
You can iterate over the array and keep a map object of the names you already processed with their index in the result array so you can access them quicker when you need to push more values.
i.e:
{
"Renault": 0,
"Ferrari": 1,
"Mercedes": 2,
"ToroRosso": 3
}
Here is a running example with the steps:
const arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
];
let map = {};
let globalIndex = 0;
let resultArray = [];
arr.forEach((currentArray) => {
const [name, ...rest] = currentArray;
if (map[name] === undefined) {
// if our map doesn't already store this value
// then store it with it's current index
map[name] = globalIndex;
// push it to the result array
resultArray[globalIndex] = currentArray;
// increment the global index
//so we can keep track of it in the next iteration
globalIndex++;
} else {
// we already have an array with this name
// grab the relevant index we previously stored
// and push the items without the name via this index
const relevantIdx = map[name];
resultArray[relevantIdx] = [
...resultArray[relevantIdx],
...rest
]
}
})
console.log(resultArray);
Related
I have two arrays like this
const arr1 = ["name", "age", "spouseName", "kids"];
const arr2 = [["John", "Jack"], [31, 44], ["Jill", "Emily"], [3, 2]];
I need to map the elements of arr1 to each nested element at the same index of arr2 so that I get result in an array with two objects like this
result = [ { "name" : "John", "age" : 31, "spouseName": "Jill", "kids" : 3 },
{ "name" : "Jack", "age" : 44, "spouseName": "Emily", "kids" : 2 }]
I have tried using nested forEach to loop over each of element in arr2 but it only spits out the items in index 1 and not at index 0 as it get overwritten in the loop
arr2.forEach((element, index) => {
element.forEach((el) => {
result[arr1[index]] = el
})
});
I know I am missing something but can't figure out
You can loop through the arrays as follows:
const arr1 = ["name", "age", "spouseName", "kids"];
const arr2 = [["John", "Jack"], [31, 44], ["Jill", "Emily"], [3, 2]];
result = arr2[0].map((_, i) => arr1.reduce((acc, k, j) => {
acc[k] = arr2[j][i];
return acc;
}, {}));
console.log(result);
You can loop through the names in array 2 and assuming the following arrays have the correct number of elements in you can use the index of that name to get the corresponding items from the other arrays:
const arr1 = [];
const arr2 = [["John", "Jack"], [31, 44], ["Jill", "Emily"], [3, 2]];
arr2[0].forEach((item, index) => {
arr1.push({
"name": item,
"age": arr2[1][index],
"spouseName": arr2[2][index],
"kids": arr2[3][index],
});
})
console.log(arr1);
If you need to use arr1 as your property names and you don't know the number of items in arr1, I would do it like this:
const arr1 = ["name", "age", "spouseName", "kids"];
const arr2 = [
["John", "Jack", "1", "2", "3"],
[31, 44, 22, 41, 42],
["Jill", "Emily", "1", "2", "3"],
[3, 2, 1, 5, 2]
];
const result = arr2[0].map((name, index) => {
let returnValue = {};
returnValue[arr1[0]] = name;
for (let i = 1; i < arr1.length; i++) {
returnValue[arr1[i]] = arr2[i][index];
}
return returnValue;
});
console.log(result)
It is a slightly more efficient way than using reduce in your map loop: https://jsbench.me/zpl6lvmb6r/1
I want to deduplicate an array of arrays. A duplicate array is one that matches a subset of element indices. In this case, say, index [1] and index [3].
const unDeduplicated = [
[ 11, 12, 13, 14, 15, ],
[ 21, 22, 23, 24, 25, ],
[ 31, 88, 33, 99, 35, ], // duplicate in indices: 1, 3 with row index 4
[ 41, 42, 43, 44, 45, ],
[ 51, 88, 53, 99, 55, ], // duplicate in indices: 1, 3 // delete this row from result
];
const deduplicated = getDeduplicated( unDeduplicated, [ 1, 3, ], );
console.log( deduplicated );
// expected result:
// [
// [ 11, 12, 13, 14, 15, ],
// [ 21, 22, 23, 24, 25, ],
// [ 31, 88, 33, 99, 35, ],
// [ 41, 42, 43, 44, 45, ],
// // this row was omitted from result because it was duplicated at indices 1 and 3 with row index 2
// ]
What is a function getDeduplicated() that can give me such a result?
I have tried the below function but it's just a start. And it isn't close to giving me the desired result. But it gives an idea of what I'm trying to do.
/**
* Returns deduplicated array as a data grid ([][] -> 2D array)
* #param { [][] } unDedupedDataGrid The original data grid to be deduplicated to include only unque rows as defined by the indices2compare.
* #param { Number[] } indices2compare An array of indices to compare for each array element.
* If every element at each index for a given row is duplicated elsewhere in the array,
* then the array element is considered a duplicate
* #returns { [][] }
*/
const getDeduplicated = ( unDedupedDataGrid, indices2compare, ) => {
let deduped = [];
unDedupedDataGrid.forEach( row => {
const matchedArray = a.filter( row => row[1] === 88 && row[3] === 99 );
const matchedArrayLength = matchedArray.length;
if( matchedArrayLength ) return;
deduped.push( row, );
});
}
I've researched some lodash functions that might help like _.filter and _.some but so far, I can't seem to find a structure that produces the desired result.
You can create Set out of the values in columns as you iterate over rows. You could choose to create sets only for the designated columns, e.g. 1 and 3 in your case. Then when iterating over each row you check if any of the designated columns in that row has such a value that is already in the corresponding set, and if it does you discard that row.
(On phone, cannot type actual code. And I guess code is pretty straight forward too)
It's probably not the most efficient algorithm, but I'd do something like
function getDeduplicated(unDeduplicated, idxs) {
const result = [];
const used = new Set();
unDeduplicated.forEach(arr => {
const vals = idxs.map(i => arr[i]).join();
if (!used.has(vals)) {
result.push(arr);
used.add(vals);
}
});
return result;
}
Idk if i understand good what you want to do but here is what i've done
list = [
[ 11, 12, 13, 14, 15, ],
[ 21, 22, 23, 24, 25, ],
[ 21, 58, 49, 57, 28, ],
[ 31, 88, 33, 88, 35, ],
[ 41, 42, 43, 44, 45, ],
[ 51, 88, 53, 88, 55, ],
[ 41, 77, 16, 29, 37, ],
];
el_list = [] // Auxiliar to save all unique numbers
res_list = list.reduce(
(_list, row) => {
// console.log(_list)
this_rows_el = [] // Auxiliar to save this row's elements
_list.push(row.reduce(
(keep_row, el) => {
// console.log(keep_row, this_rows_el, el)
if(keep_row && el_list.indexOf(el)==-1 ){
el_list.push(el)
this_rows_el.push(el)
return true
}else if(this_rows_el.indexOf(el)!=-1) return true // Bypass repeated elements in this row
else return false
}, true) ? row : null) // To get only duplicated rows (...) ? null : row )
return _list
}, []
)
console.log(res_list)
This is fairly concise. It uses nested filters. It will also work for any number of duplicates, keeping only the first one.
init = [
[ 11, 12, 13, 14, 15],
[ 21, 22, 23, 24, 25],
[ 31, 88, 33, 99, 35],
[ 41, 42, 43, 44, 45],
[ 51, 88, 53, 99, 55],
];
var deDuplicate = function(array, indices){
var res = array.filter(
(elem) => !array.some(
(el) =>
array.indexOf(el) < array.indexOf(elem) && //check that we don't discard the first dupe
el.filter((i) => indices.includes(el.indexOf(i))).every((l,index) => l === elem.filter((j) => indices.includes(elem.indexOf(j)))[index])
//check if the requested indexes are the same.
// Made a bit nasty by the fact that you can't compare arrays with ===
)
);
return(res);
}
console.log(deDuplicate(init,[1,3]));
Not the most efficient but this will remove dups of more than one duplicate array
const unDeduplicated = [ [ 11, 12, 13, 14, 15, ], [ 21, 22, 23, 24, 25, ], [ 31, 88, 33, 99, 35, ], [ 41, 33, 43, 44, 45, ], [ 51, 88, 53, 99, 55, ]]
const unDeduplicated1 = [
[ 11, 12, 13, 14, 15, ],
[ 21, 22, 23, 24, 25, ],// duplicate in indices: 1, 3 with row index 3
[ 31, 88, 33, 99, 35, ], // duplicate in indices: 1, 3 with row index 4
[ 21, 22, 43, 24, 45, ],// duplicate in indices: 1, 3 // delete this
[ 51, 88, 53, 99, 55, ], // duplicate in indices: 1, 3 // delete this row from result
];
function getDeduplicated(arr, arind) {
for (let i = 0; i < arr.length; i++) {
for (let j = 1 + i; j < arr.length; j++) {
if (arr[j].includes(arr[i][arind[0]]) && arr[j].includes(arr[i][arind[1]])) {
arr.splice(j, 1)
i--
} else continue
}
}
return arr
}
const deduplicated = getDeduplicated(unDeduplicated, [1, 3]);
const deduplicated2 = getDeduplicated(unDeduplicated1, [1, 3]);
console.log(deduplicated)
console.log("#####################")
console.log(deduplicated2)
I have two arrays:
arr1 = [name, speed, power, energy];
arr2 = [
[Ed, 10, 20, 30],
[Robert, 15, 25, 35],
[Paul, 8, 18, 28]
];
How can I combine the two array's to an array of objects, using the first array for keys and the second one for values?
arr3 = [
{
name: "Ed",
speed:"10",
power:"20",
energy:"30"
},
{
name: "Robert",
speed:"15",
power:"25",
energy:"35"
},
{
name: "Paul,
speed:"8",
power:"18",
energy:"28"
}
];
You can simply create an array of objects using map
arr2.map(row => {
const name = item[0];
const speed = item[1];
const power = item[2];
const energy = item[3];
return { name, speed, power, energy }
})
Running this on your given arr2 gives the following result
var arr2 = [['Ed', 10, 20, 30],['Robert', 15, 25, 35],['Paul', 8, 18, 28]];
var arr3 = arr2.map(row => {
const name = item[0];
const speed = item[1];
const power = item[2];
const energy = item[3];
return { name, speed, power, energy }
});
console.log(arr3)
// arr3 = [
// {name: "Ed", speed:10, power:20, energy:30},
// {name: "Robert", speed:15, power:25, energy:35},
// {name: "Paul", speed:8, power:18, energy:28}
// ]
Firstly, I am assuming the tokens name, speed, power, energy are actually strings and you forgot to include the quotes.
The Object.fromEntries method takes an array of tuples (two-item arrays) and converts it into an object.
If we zip the keys from arr1 with the values from each array in arr2, we can acheive the desired mapping.
arr1 = ["name", "speed", "power", "energy"];
arr2 = [["Ed", 10, 20, 30],["Robert", 15, 25, 35],["Paul", 8, 18, 28]];
arr3 = arr2.map(objArr =>
Object.fromEntries(arr1.map((key, i) =>
[key, objArr[i]] // key-value tuple
))
)
console.log(arr3);
Ruby has this really useful method called zip, so you want basically that for each of arr2 but in JavaScript. In other words, zip arr1 keys with each person's properties.
Below is a snippet that implements a basic zip function and then uses it to create the object in the format you're looking for:
arr1 = ["name", "speed", "power", "energy"];
arr2 = [
["Ed", 10, 20, 30],
["Robert", 15, 25, 35],
["Paul", 8, 18, 28],
];
Array.prototype.zip = function(a) {
return this.map((k, i) => [k, a[i]]);
};
arr3 = arr2.map(p => Object.fromEntries(arr1.zip(p)));
console.log(arr3);
I am wondering how to assign default values when destructing a nested array.
I have myArr array which has a nested array [12, 25, 1, 6]
let myArr = [11, 100, 33, [12, 25, 1, 6], 77]
I want to assign a default value to four when destructing myArr as below
const[ one = 999, two = 999, three = 999, four = [ ], five = 999] = myArr
And I also want to destructure elements of the nested array.
const[ one = 999, two = 999, three = 999, [innerOne = 1, ...rest ], five = 999] = myArr
Is it possible to assign a default value to variable four and destructure the elements of the nested array [12, 25, 1, 6] concurrently in one line?
You can do this by destructuring the array as an object. When destructuring an object, you can assign aliases, and destructure a property more than once (index 3 in this case).
const myArr = [11, 100, 33, [12, 25, 1, 6], 77]
const {
0: one = 999,
1: two = 999,
2: three = 999,
3: four = [],
3: [innerOne = 1, ...rest ],
4: five = 999
} = myArr
console.log(one, two, three, four, innerOne, rest, five)
var array = [355, 1, 488, 6, 4, 78, 63, 4, 3, 1];
// array = [9, 2, 5, 4, 6],
// array = ["1001", "25", "36", "25"],
// array = ["c1-ca-10-1a-11-f4","c1-ca-10-1a-11-f5","c1-ca-10-1a-11-f1" //];
assetData = new Set();
array.forEach(function(data) {
assetData.add(data);
});
assetData = Array.from(assetData)
assetData.sort(function() {
return 0.5 - Math.random();
});
console.log(assetData);
var newArray = [];
Array.prototype.push.apply(newArray, assetData
);
In above code i want to sort all arrays.i have 4 type of array i need to sort all of them.
Below is the best way to handle all kind of array element sorting.
var //array = [355, 1, 488, 6, 4, 78, 63, 4, 3, 1];
// array = [9, 2, 5, 4, 6],
//array = ["1001", "25", "36", "25"],
array = ["c1-ca-10-1a-11-f4","c1-ca-10-1a-11-f5","c1-ca-10-1a-11-f1"];
assetData = new Set();
array.forEach(function(data) {
assetData.add(data);
});
assetData = Array.from(assetData)
assetData.sort(function(a, b){return a-b});
console.log(assetData);
var newArray = [];
Array.prototype.push.apply(newArray, assetData
);