Reputation: 148
I am trying to return a selection of data from a nested array to a new nested array but the data is just being pushed into array.
var selection = [0,1,3,4];
var allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']]
var selectedProductData = []
for(var apd=0; apd<allProductData.length; apd++) {
for(var spd=0; spd<allProductData[apd].length; spd++) {
for(var s=0; s<selection.length; s++) {
if(allProductData[apd].indexOf(allProductData[apd][spd]) === selection[s]) {
selectedProductData.push(allProductData[apd][spd])
}
}
}
}
console.log(selectedProductData)
This returns the following
[
"Item1Sku","Item1Name","Item1Price","Item1Available",
"Item2Sku","Item2Name","Item2Price","Item2Available",
"Item3Sku","Item3Name","Item3Price","Item3Available"
]
What I want is
[
["Item1Sku","Item1Name","Item1Price","Item1Available"],
["Item2Sku","Item2Name","Item2Price","Item2Available"],
["Item3Sku","Item3Name","Item3Price","Item3Available"]
]
Any help with this would be great.
Upvotes: 1
Views: 685
Reputation:
Something like the below snippet does the work you want. Additionally see:
let selection = [0,1,3,4];
let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
let filtered = allProductData.map(item => item.filter((val,index) => selection.includes(index)));
console.log(filtered);
There was a lot of noise about this syntax (snippet below).on comments, about the fact that the callback function in
filter()
having to evaluate to true. The actual words in MDN are:
Function is a predicate, to test each element of the array. Return true to keep the element, false otherwise
let selection = [0,1,3,4];
let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
let filtered = allProductData.map(item =>
item.filter((val,index) => {
if(selection.includes(index)) {
return val;
}
})
);
console.log(filtered);
So here are some examples that do the exact same thing without raising an error. In all cases what is returned by .filter()
is the logical true that will match the conditions in the callback function.
let selection = [0,1,3,4];
let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
let filtered = allProductData.map(item =>
item.filter((val,index) => {
if(selection.includes(index)) {
return index > 3; // this will return only the itemXAvailability
}
})
);
console.log(filtered);
The above snippet could be re-written this way.
let selection = [0,1,3,4];
let allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
let filtered = allProductData.map(item =>
item.filter((val,index) => selection.includes(index) && index > 3)
);
console.log(filtered);
Two more examples using Boolean
true, false as values of the array to test.
let selection = [0,1,3,4];
let allProductData = [[true,true, false, true, false, true], [true,true,true,true,true,true], [false,false,false,false,false,false]];
let filtered = allProductData.map(item =>
item.filter((val,index) => selection.includes(index) && index > 3)
);
console.log(filtered);
filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));
Notice the difference in the output.
let selection = [0,1,3,4];
let allProductData = [[true,true, false, true, false, true], [true,true,true,true,true,true], [false,false,false,false,false,false]];
let filtered = allProductData.map(item =>
item.filter((val,index) => {
if(selection.includes(index) && index > 3) {
return val;
}
})
);
console.log(filtered);
filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));
Two more examples using numbers. Output differs for value being 0
.
let selection = [0,1,3,4];
let allProductData = [[1,2,3,4,5,6], [6,5,4,3,2,1], [8,8,8,8,0,8]];
let filtered = allProductData.map(item =>
item.filter((val,index) => selection.includes(index) && index > 3)
);
console.log(filtered);
filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));
let selection = [0,1,3,4];
let allProductData = [[1,2,3,4,5,6], [6,5,4,3,2,1], [8,8,8,8,0,8]];
let filtered = allProductData.map(item =>
item.filter((val,index) => {
if(selection.includes(index) && index > 3) {
return val;
}
})
);
console.log(filtered);
filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));
What would be the difference when using null
as our value.
let selection = [0,1,3,4];
let allProductData = [[null,null,null,null,null,null], [null,null,null,null,null,null], [null,null,null,null,null,null]];
let filtered = allProductData.map(item =>
item.filter((val,index) => selection.includes(index) && index > 3)
);
console.log(filtered);
filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));
let selection = [0,1,3,4];
let allProductData = [[null,null,null,null,null,null], [null,null,null,null,null,null], [null,null,null,null,null,null]];
let filtered = allProductData.map(item =>
item.filter((val,index) => {
if(selection.includes(index) && index > 3) {
return val;
}
})
);
console.log(filtered);
filtered.forEach((item) => item.forEach((val) => console.log(typeof(val))));
Upvotes: 0
Reputation: 4616
Use array.map and array.filter for it.
var selection = [0,1,3,4];
var allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
let result = allProductData.map(data => {
return data.filter((el, ind) => selection.indexOf(ind)!=-1);
})
console.log(result);
Upvotes: 0
Reputation: 2610
Use for...of
instead of i=0;i<x;i++
it's more readable and can help you with the flow.
Also you can reach each element index inside your first loop, instead of setting selection
array. you would still write it only one time and spare a loop.
var allProductData = [['Item1Sku', 'Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'],['Item2Sku', 'Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'],['Item3Sku', 'Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']];
var selectedProductData = [];
for (let data of allProductData) {
selectedProductData.push([data[0], data[1], data[3], data[4]]);
}
console.log(selectedProductData)
Upvotes: 1
Reputation: 5853
Use Array.prototype.reduce
to reduce the array and check if each current element's index lies within the selection array or not, if it does then push it.
const selection = [0, 1, 3, 4];
const allProductData = [
['Item1Sku', 'Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'],
['Item2Sku', 'Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'],
['Item3Sku', 'Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']
];
const selectedProductData = allProductData.reduce((acc, curr) => {
const filtered = curr.filter((product, idx) => selection.includes(idx));
if (filtered.length) {
acc.push(filtered);
}
return acc;
}, []);
console.log(selectedProductData);
Upvotes: 1
Reputation: 68933
You should create another array inside the first for loop and push the result in that array first, then push that array into the final array:
var selection = [0,1,3,4];
var allProductData = [['Item1Sku','Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku','Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku','Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']]
var selectedProductData = []
for(var apd=0; apd<allProductData.length; apd++) {
var temp = []; // declare an array here
for(var spd=0; spd<allProductData[apd].length; spd++) {
for(var s=0; s<selection.length; s++) {
if(allProductData[apd].indexOf(allProductData[apd][spd]) === selection[s]) {
temp.push(allProductData[apd][spd]); // push the result
}
}
}
selectedProductData.push(temp); // push the array into the final array
}
console.log(selectedProductData)
Upvotes: 0
Reputation: 386624
You could map the data and the values at the wanted index.
const
selection = [0, 1, 3, 4],
allProductData = [['Item1Sku', 'Item1Name', 'Item1Desc', 'Item1Price', 'Item1Available', 'Item1Margin'], ['Item2Sku', 'Item2Name', 'Item2Desc', 'Item2Price', 'Item2Available', 'Item2Margin'], ['Item3Sku', 'Item3Name', 'Item3Desc', 'Item3Price', 'Item3Available', 'Item3Margin']],
selectedProductData = allProductData.map(values => selection.map(i => values[i]));
console.log(selectedProductData);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 3