Related
I have an object of filters.
filters = {color: 'black', size: '40'}
i want to return a filtered array of my data. Here's a sample of my data:
data = [
{
id: 1,
name: "Good Engine001"
categories: ['machine'],
color: ['Black', 'white'],
size: [30, 40, 50]
},
{
id: 2,
name: "Good Plane"
categories: ['machine', 'plane'],
color: ['Grey', 'white'],
size: [10, 30, 50]
},
{
id: 3,
name: "Good Chair001"
categories: ['furniture', 'chair'],
color: ['Brown', 'Black'],
size: [3, 5, 40]
}
];
filteredProducts = data.filter((item) =>
Object.entries(filters).every(([key, value]) =>
item[key].includes(value)
)
I'm quite stuck here. I am trying to set the filtered products to be equal to the few entries that matches with the values provided in my filters object. what am i doing wrong?
I was expecting this:
filteredProducts = [
{
id: 1,
name: "Good Engine001"
categories: ['machine'],
color: ['Black', 'white'],
size: [30, 40, 50]
},
{
id: 3,
name: "Good Chair001"
categories: ['furniture', 'chair'],
color: ['Brown', 'Black'],
size: [3, 5, 40]
}
];
But i got the same data.
If you want to compare case-insensitively and loosely compare numbers to their string equivalents, you won't be able to use Array.prototype.includes() since it uses strict comparisons.
Instead, you'll need to use Array.prototype.some() and compare stringified values using base sensitivity...
// Your data with typos fixed and minified
const data = [{"id":1,"name":"Good Engine001","categories":["machine"],"color":["Black","white"],"size":[30,40,50]},{"id":2,"name":"Good Plane","categories":["machine","plane"],"color":["Grey","white"],"size":[10,30,50]},{"id":3,"name":"Good Chair001","categories":["furniture","chair"],"color":["Brown","Black"],"size":[3,5,40]}]
// Stringifies values and compares with "base" sensitivity
const comparator = (dataValue, filterValue) =>
dataValue
.toString()
.localeCompare(filterValue, undefined, { sensitivity: "base" }) === 0;
// Checks various data types using the above comparator
const predicate = (dataValue, filterValue) => {
// Check arrays
if (Array.isArray(dataValue)) {
return dataValue.some((value) => comparator(value, filterValue));
}
// Exclude nested objects and null
if (typeof dataValue !== "object") {
return comparator(dataValue, filterValue);
}
return false;
};
const filters = { color: "black", size: "40" };
const filteredProducts = data.filter((item) =>
Object.entries(filters).every(([key, value]) => predicate(item[key], value))
);
console.log(filteredProducts);
.as-console-wrapper { max-height: 100% !important; }
color names are capital in data while they are not in filter.
'40' is string literal in filter, while it is number in your data.
and also your data should be like this with curly braces around each item:
const data = [
{
id: 1,
name: "Good Engine001",
categories: ['machine'],
color: ['Black', 'white'],
size: [30, 40, 50]
},
{
id: 2,
name: "Good Plane",
categories: ['machine', 'plane'],
color: ['Grey', 'white'],
size: [10, 30, 50]
},
{
id: 3,
name: "Good Chair001",
categories: ['furniture', 'chair'],
color: ['Brown', 'Black'],
size: [3, 5, 40]
}
];
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have array of objects where I want to filter and combine results based on specific id. This is example:
[
{
id: 1,
items: [
{
id: 10,
values: [11],
},
{
id: 20,
values: [13, 14, 15],
},
],
},
{
id: 2,
items: [
{
id: 10,
values: [12],
},
{
id: 20,
values: [13, 15],
},
],
},
];
And this is expected result:
[
{
id: 10,
values: [11, 12],
},
{
id: 20,
values: [13, 14, 15],
},
];
I also need to filter duplicates. Thanks
Note: What if I want this result?
[
{
// here I want value for id 10 (it will be always one number)
value: 11,
// here I want values for id 20 (array of numbers) => remove possible duplicates
values: [13, 14, 15],
},
{
// here I want value for id 10 (it will be always one number)
value: 12,
// here I want values for id 20 (array of numbers) => remove possible duplicates
values: [13, 15],
},
];
I tried the same approach with Map, but without success. Basically I want to combine values based on ids.
You could do with Array.flatMap to filter all items in single array.
Then recreate the array with Array.reduce and push the value based on id into new value object
And use Array.filter ignore the duplicate values on array
Object.values return only the value of object in array format
Older
const arr = [ { id: 1, items: [ { id: 10, values: [11], }, { id: 20, values: [13, 14, 15], }, ], }, { id: 2, items: [ { id: 10, values: [12], }, { id: 20, values: [13, 15], }, ], }, ];
const res = Object.values(arr.flatMap(({items})=> items)
.reduce((acc,{id,values})=>{
acc[id] = acc[id] ?? {id,values:[]};
//check the object exist or not
let newArr = acc[id]['values'].concat(values);
let valArr = newArr.filter((v,i)=>newArr.indexOf(v) === i)
//remove the duplicates
acc[id]['values'] = valArr
return acc
},{}))
console.log(res)
Updated
const arr = [ { id: 1, items: [ { id: 10, values: [11], }, { id: 20, values: [13, 14, 15], }, ], }, { id: 2, items: [ { id: 10, values: [12], }, { id: 20, values: [13, 15], }, ], }, ];
function filterMethod(arr,value,values){
return arr.map(({items})=> ({
value:detector(items,value)[0],
values:detector(items,values)
}))
}
function detector(items,idVal){
let ind = items.findIndex(({id})=> id === idVal);
return ind > -1 ? items[ind]['values'] : ['']
}
console.log(filterMethod(arr,10,20))
I have an array and I need to filter out keys based on an input string. Only OLD_VAL is static, the rest are dynamic. I tried using the variable but it is not bringing that key
let input = VKORG,VTWEG,MATNR;
let arr = [
{
VKORG: 1100,
VTWEG: 10,
MATNR: 12,
RATE: 0.01,
VALUE: 1,
OLD_VAL: 12,
},
{
VKORG: 2100,
VTWEG: 99,
MATNR: 13,
RATE: 0.11,
VALUE: 11,
OLD_VAL: 12,
},
];
Output:
[
{
VKORG: "1100",
VTWEG: 10,
MATNR: "12",
OLD_VAL: 12,
},
{
VKORG: "2100",
VTWEG: 99,
MATNR: "13",
OLD_VAL: 12,
},
];
Code tried
let filterResults = results.map(({ OLD_VAL,input }) => ({ OLD_VAL, input }))
Assuming input is an array of strings, you can use Object.entries and create an object at each iteration consisting of the key-value pairs where keys are obtained from the input.
const input = ['VKORG', 'VTWEG', 'MATNR']
const arr = [{
VKORG: 1100,
VTWEG: 10,
MATNR: 12,
RATE: 0.01,
VALUE: 1,
OLD_VAL: 12,
},
{
VKORG: 2100,
VTWEG: 99,
MATNR: 13,
RATE: 0.11,
VALUE: 11,
OLD_VAL: 12,
}
]
const result = arr.map(el => Object.fromEntries(input.map(key => [key, el[key]]).concat([['OLD_VAL', el.OLD_VAL]])));
console.log(result);
If the input isn't an array of strings but is a string('VKORG,VTWEG,MATNR') then you can split it and use the above logic.
const input = 'VKORG,VTWEG,MATNR';
const inputArr = input.split(',');
const arr = [{
VKORG: 1100,
VTWEG: 10,
MATNR: 12,
RATE: 0.01,
VALUE: 1,
OLD_VAL: 12,
},
{
VKORG: 2100,
VTWEG: 99,
MATNR: 13,
RATE: 0.11,
VALUE: 11,
OLD_VAL: 12,
}
]
// using a spread operator instead of concat
const result = arr.map(el => Object.fromEntries([
...inputArr.map(key => [key, el[key]]), ['OLD_VAL', el.OLD_VAL]
]));
console.log(result);
You can do this with either way :
Good old for loop
const newArr = [];
for(let obj of arr) {
let newObj = {}
for(let key of input) {
console.log(key)
newObj[key] = obj[key]
}
newArr.push(newObj);
}
Or using map and reduce methods of the Array interface:
arr.map( e => input.reduce((acc, key) => {
acc[key] = e[key];
return acc;
},{}))
PS: dont forget that object keys are strings so your input variable should be :
const input = ['VKORG', 'VTWEG', 'MATNR']
I want to get the array of objects created from two simple arrays:
const array1 = [20, 2, 35, 86]
const array2 = [8, 86, 15, 23, 35, 44]
The expected result:
const result = [
{ id: 20, value: false },
{ id: 2, value: false },
{ id: 35, value: true },
{ id: 86, value: true },
];
The array1 length is the one that matters. So I need to find matched values in both arrays as showed in the expected result.
Thank you very much for your help.
You can combine map with includes:
array1.map(i => ({id: i, value: array2.includes(i)}))
Should be simple. Loop through the first array using Array.map & return an object.
const array1 = [20, 2, 35, 86]
const array2 = [8, 86, 15, 23, 35, 44]
const result = array1.map(i => ({ id: i, value: array2.includes(i) }))
console.log(result)
Create a set from the second array:
const a2set = new Set(array2);
then map your first array:
array1.map(v1 => ({id:v1, value: a2set.has(v1)}))
Start a loop against first array and check if that element exists in second array or not.
If element exists push it to array containing objects with flag true or else as false.
const array1 = [20, 2, 35, 86]
const array2 = [8, 86, 15, 23, 35, 44]
var objArray = []
array1.forEach(function(elem){
objArray.push({
id : elem,
value : array2.indexOf(elem) != -1 ? true : false
});
});
console.log(objArray);
You can use array indexOf to find if the item is inside the second array.
const array1 = [20, 2, 35, 86];
const array2 = [8, 86, 15, 23, 35, 44];
let output = [];
array1.forEach((number) => {
output.push({
id: number,
value: array2.indexOf(number) !== -1
});
});
console.log(output);
Try a simple for loop:
const array1 = [20, 2, 35, 86];
const array2 = [8, 86, 15, 23, 35, 44];
var res = [];
for (var i = 0; i < array1.length; i++) {
if (array2.includes(array1[i])) {
res.push({ id: array1[i], value: true });
} else {
res.push({ id: array1[i], value: false });
}
}
console.log(res);
Try the following. If performance is important, or if the arrays might include a large amount of elements, I'd consider using sets for better lookup performance.
const array1 = [20, 2, 35, 86]
const array2 = [8, 86, 15, 23, 35, 44]
const result = array1.map(element => {
return {
id: element,
value: array2.includes(element)
};
})
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I have an array of arrays (2d array), and I want to convert it into an array of objects. In the resulting array, I would like each object to have a key-name (see expected output below)
data = [
['Apple', 'Orange', 'Banana', 'Pears', 'Peach'],
[40, 35, 25, 58, 84],
[2, 4, 4, 3, 1, 2],
['Red', 'Yellow', 'Green', 'Violet', 'Blue']
];
My expected result:
expected_result = [
{name: 'Apple', price: 40, quantity: 2, color: 'Red'},
{name: 'Orange', price: 35, quantity: 4, color: 'Yellow'},
{name: 'Banana', price: 25, quantity: 4, color: 'Green'},
{name: 'Pears', price: 58, quantity: 1, color: 'Violet'},
{name: 'Peach', price: 84, quantity: 2, color: 'Blue'}
];
Note The iteration of each array (in data) should be consecutive so that it gives the expected result
Seems to be there is one item extra in the quantity values. I have updated
[2, 4, 4, 3, 1, 2] to [2, 4, 4, 1, 2] removed 3 to match the result, hoping its a typo.
let data = [
["Apple", "Orange", "Banana", "Pears", "Peach"],
[40, 35, 25, 58, 84],
[2, 4, 4, 1, 2],
["Red", "Yellow", "Green", "Violet", "Blue"]
];
let output = [];
let props = ["name", "price", "quantity", "color"];
function updateInfo(row, prop){
row.filter((value, index) => {
if (output[index]) {
output[index][prop] = value;
} else {
output.push({
[prop]: value
});
}
});
};
data.filter((row, index) => {
updateInfo(row, props[index]);
});
console.log(output);
One solution consist of creating first a Map between the outter-array indexes and the property (or key) name you want to assign to them (however this could be replaced by an array like this ["name","price","quantity","color"]). Also, you can obtain the minimun length of the inner arrays to later check for non-creation of objects that won't have all the properties. After you do this pre-initialization, you can use Array.reduce() to generate your expected result:
const data = [
['Apple', 'Orange', 'Banana', 'Pears', 'Peach'],
[40, 35, 25, 58, 84],
[2, 4, 4, 3, 1, 2],
['Red', 'Yellow', 'Green', 'Violet', 'Blue']
];
let mapIdxToProp = new Map([[0, "name"],[1, "price"],[2, "quantity"],[3, "color"]]);
let minLen = Math.min(...data.map(x => x.length));
let res = data.reduce((acc, arr, idx) =>
{
arr.forEach((x, j) =>
{
(j < minLen) && (acc[j] = acc[j] || {}, acc[j][mapIdxToProp.get(idx)] = x);
});
return acc;
}, []);
console.log(res);
The simplest (not most efficient) solution in my opinion is to simply loop through the array, adding to another array as you go.
let arr = [
['Apple', 'Orange', 'Banana', 'Pears', 'Peach'],
[40, 35, 25, 58, 84],
[2, 4, 4, 1, 2],
['Red', 'Yellow', 'Green', 'Violet', 'Blue']
];
let keys = ["name", "price", "quantity", "color"];
let output = [];
//Add's blank objects too the output array
for (let i = 0; i < arr[0].length; i++) {
output.push({});
}
//Loops through the array
for (let i = 0; i < arr.length; i++) {
//Loops through the sub array
for (let x = 0; x < arr[i].length; x++) {
//Adds the sub array to the key that corresponds to it
output[x][keys[i]] = arr[i][x];
}
}
console.log(output);