Compare values in two arrays of obj and remove from first - javascript

var firstOne = [
{ id: 22, value: 'hi there' },
{ id: 28, value: 'here' },
{ id: 77, value: 'what' }
];
var secondOne = [
{ id: 2, value: 'bond' },
{ id: 8, value: 'foobar' },
{ id: 87, value: 'what' }
];
I'm looking for the best approach to compare two arrays of objects by value. If value is same in both, then remove it from firstOne which would result in:
var firstOne = [
{ id: 22, value: 'hi there' },
{ id: 28, value: 'here' }
];
var secondOne = [
{ id: 2, value: 'bond' },
{ id: 8, value: 'foobar' },
{ id: 87, value: 'what' }
];
Javascript or Angular solutions would be appreciated. Thanks

You could use Set for the filtering.
var firstOne = [{ id: 22, value: 'hi there' }, { id: 28, value: 'here' }, { id: 77, value: 'what' }],
secondOne = [{ id: 2, value: 'bond' }, { id: 8, value: 'foobar' }, { id: 87, value: 'what' }],
mySet = new Set;
secondOne.forEach(function (a) {
mySet.add(a.value);
});
firstOne = firstOne.filter(function (a) {
return !mySet.has(a.value);
});
console.log(firstOne);
ES6
var firstOne = [{ id: 22, value: 'hi there' }, { id: 28, value: 'here' }, { id: 77, value: 'what' }],
secondOne = [{ id: 2, value: 'bond' }, { id: 8, value: 'foobar' }, { id: 87, value: 'what' }],
mySet = new Set;
secondOne.forEach(a => mySet.add(a.value));
firstOne = firstOne.filter(a => !mySet.has(a.value));
console.log(firstOne);

Related

Getting an array from array of array objects

I have an array which consists of an array objects as shown:
dataArr = [
{
id: 1,
arrObj: [
{
id: 11,
label: 'apple'
},
{
id: 12,
label: 'ball'
}
]
},
{
id: 2,
arrObj: [
{
id: 21,
label: 'car'
},
{
id: 22,
label: 'dog'
}
]
}
];
I need to extract an array consisting of only arrObj objects:
var newArr = [
{
id: 11,
label: 'apple'
},
{
id: 12,
label: 'ball'
},
{
id: 21,
label: 'car'
},
{
id: 22,
label: 'dog'
}
];
Tried using reduce method unsuccessfully:
dataArr.reduce((previousValue, currentValue, currentIndex, array) => {
return previousValue. arrObj.concat(currentValue.arrObj)
});
Let me know how to do this. Thanks
let dataArr = [
{
id: 1,
arrObj: [
{
id: 11,
label: 'apple'
},
{
id: 12,
label: 'ball'
}
]
},
{
id: 2,
arrObj: [
{
id: 21,
label: 'car'
},
{
id: 22,
label: 'dog'
}
]
}
];
let result = dataArr.flatMap(e => e.arrObj)
console.log(result)
You were pretty close.
There's no arrObj property in your result, it's just an array.
You need to provide an empty array as the initial value argument to reduce().
const dataArr = [{
id: 1,
arrObj: [{
id: 11,
label: 'apple'
},
{
id: 12,
label: 'ball'
}
]
},
{
id: 2,
arrObj: [{
id: 21,
label: 'car'
},
{
id: 22,
label: 'dog'
}
]
}
];
const newArr = dataArr.reduce((previousValue, currentValue) => {
return previousValue.concat(currentValue.arrObj)
}, []);
console.log(newArr);
You could use in one line by using Spread Operator...
dataArr.reduce((previousValue, currentValue) => [...previousValue?.arrObj, ...currentValue?.arrObj]);
Tip: use Optional chaining ?. in case there is no property arrObj!
You can use the Array#reduce method as follows:
let dataArr = [
{
id: 1,
arrObj: [
{
id: 11,
label: 'apple'
},
{
id: 12,
label: 'ball'
}
]
},
{
id: 2,
arrObj: [
{
id: 21,
label: 'car'
},
{
id: 22,
label: 'dog'
}
]
}
];
let newArr = dataArr.reduce((acc,cur) => [...acc, ...cur.arrObj], []);
console.log( newArr );

Filter object from array based on multiple nested values

Basically I'm trying to figure out the cleanest way to select one item from an array, only if all certain values exist.
const filterValues = ['blue', '30cm', 'true'];
const products = [
{
details: [
{ id: 1, value: 'red' },
{ id: 2, value: '30cm' },
{ id: 3, value: 'true' },
{ id: 4, value: '123432'}
],
name: "Product 1"
},
{
details: [
{ id: 5, value: 'blue' },
{ id: 6, value: '30cm' },
{ id: 7, value: 'true' },
{ id: 8, value: '98348'}
],
name: "Product 2"
},
{
details: [
{ id: 9, value: 'black' },
{ id: 10, value: '40cm' },
{ id: 11, value: 'false' },
{ id: 12, value: '578347'}
],
name: "Product 3"
},
]
Only Product 2 contains all the filter values, so I want to return that product.
I have tried:
products.filter(p => {
p.details.find(k => filterValues.includes(k.value));
})
but this returns if any of the values satisfies the condition rather than if all of them are included. This is the main issue here. I'm struggling with finding a way to filter if only all these values int he array are present in the object.
Use Array#every.
const filterValues = ['blue', '30cm', 'true'];
const products = [
{
details: [
{ id: 1, value: 'red' },
{ id: 2, value: '30cm' },
{ id: 3, value: 'true' },
{ id: 4, value: '123432'}
],
name: "Product 1"
},
{
details: [
{ id: 5, value: 'blue' },
{ id: 6, value: '30cm' },
{ id: 7, value: 'true' },
{ id: 8, value: '98348'}
],
name: "Product 2"
},
{
details: [
{ id: 9, value: 'black' },
{ id: 10, value: '40cm' },
{ id: 11, value: 'false' },
{ id: 12, value: '578347'}
],
name: "Product 3"
},
]
console.log(products.filter(p => filterValues.every(fv => p.details.map(d => d.value).includes(fv))));

Assign new properties to an array of Objects

I have an array of Objects
const options = [
{ id: 1, name: "Back Pain" },
{ id: 2, name: "Body aches" },
{ id: 3, name: "Cold Sores" },
{ id: 4, name: "Cough" },
{ id: 5, name: "Constipation" },
];
I am trying to write a function that will assign new properties to the object.
The output I am looking for is:
const options = [
{ value: 1, label: "Back Pain" },
{ value: 2, label: "Body aches" },
{ value: 3, label: "Cold Sores" },
{ value: 4, label: "Cough" },
{ value: 5, label: "Constipation" },
];
I have tried to loop through the array using a for loop, but can not figure it out.
Thanks for the help:)
You can do it like this:
const data=[{ id: 1, name: "Back Pain" },
{ id: 2, name: "Body aches" },
{ id: 3, name: "Cold Sores" },
{ id: 4, name: "Cough" },
{ id: 5, name: "Constipation" },
];
var result = data.map(({id:value, name:label})=>({value, label}));
console.log(result);

lodash recursively find item in array

What might be the easiest solution in lodash to recursively find item in array by, for example, 'text' field with value 'Item-1-5-2'?
const data = [
{
id: 1,
text: 'Item-1',
children: [
{ id: 11, text: 'Item-1-1' },
{ id: 12, text: 'Item-1-2' },
{ id: 13, text: 'Item-1-3' },
{ id: 14, text: 'Item-1-4' },
{
id: 15,
text: 'Item-1-5',
children: [
{ id: 151, text: 'Item-1-5-1' },
{ id: 152, text: 'Item-1-5-2' },
{ id: 153, text: 'Item-1-5-3' },
]
},
]
},
{
id: 2,
text: 'Item-2',
children: [
{ id: 21, text: 'Item-2-1' },
{ id: 22, text: 'Item-2-2' },
{ id: 23, text: 'Item-2-3' },
{ id: 24, text: 'Item-2-4' },
{ id: 25, text: 'Item-2-5' },
]
},
{ id: 3, text: 'Item-3' },
{ id: 4, text: 'Item-4' },
{ id: 5, text: 'Item-5' },
];
Thank You!
In plain Javascript, you could use Array#some recursively.
function getObject(array, key, value) {
var o;
array.some(function iter(a) {
if (a[key] === value) {
o = a;
return true;
}
return Array.isArray(a.children) && a.children.some(iter);
});
return o;
}
var data = [{ id: 1, text: 'Item-1', children: [{ id: 11, text: 'Item-1-1' }, { id: 12, text: 'Item-1-2' }, { id: 13, text: 'Item-1-3' }, { id: 14, text: 'Item-1-4' }, { id: 15, text: 'Item-1-5', children: [{ id: 151, text: 'Item-1-5-1' }, { id: 152, text: 'Item-1-5-2' }, { id: 153, text: 'Item-1-5-3' }, ] }, ] }, { id: 2, text: 'Item-2', children: [{ id: 21, text: 'Item-2-1' }, { id: 22, text: 'Item-2-2' }, { id: 23, text: 'Item-2-3' }, { id: 24, text: 'Item-2-4' }, { id: 25, text: 'Item-2-5' }, ] }, { id: 3, text: 'Item-3' }, { id: 4, text: 'Item-4' }, { id: 5, text: 'Item-5' }, ];
console.log(getObject(data, 'text', 'Item-1-5-2'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
It's the perfect spot for a recursive function.
function findText(items, text) {
if (!items) { return; }
for (const item of items) {
// Test current object
if (item.text === text) { return item; }
// Test children recursively
const child = findText(item.children, text);
if (child) { return child; }
}
}
That's also the best way to get the maximum performances. Traversal is some in depth-first-search way.

Build Object Recursive

I have a Object which looks like the following obj.
var obj = [
{ id: 1, name: "animals" },
{ id: 2, name: "animals_cat" },
{ id: 3, name: "animals_dog" },
{ id: 4, name: "animals_weazle" },
{ id: 5, name: "animals_weazle_sand shadow weazle" },
{ id: 11, name: "fruits" },
{ id: 32, name: "fruits_banana" },
{ id: 10, name: "threes" },
{ id: 15, name: "cars" }
];
The Object should be converted into the following scheme:
var items = [
{ id: 11, name: "fruits", items: [
{ id: 32, name: "banana" }
]},
{ id: 10, name: "threes" },
{ id: 1, name: "animals", items: [
{ id: 2, name: "cat" },
{ id: 3, name: "dog" },
{ id: 4, name: "weazle", items: [
{ id: 5, name: "sand shadow weazle" }
]}
]},
{ id: 15, name: "cars" }
];
I tried a lot but unfortunately without any success. I did $.each on obj, did a split('_') on it and pushed it to items. But how can I do it for unlimited depth and push it into the right category?
I'm happy for any help.
Maybe this helps.
It works with Array.prototype.forEach for processing obj, Array.prototype.reduce for getting the right branch and Array.prototype.some for the right array element for inserting the new object.
This proposal works for sorted and consistent data.
var obj = [
{ id: 1, name: "animals" },
{ id: 2, name: "animals_cat" },
{ id: 3, name: "animals_dog" },
{ id: 4, name: "animals_weazle" },
{ id: 5, name: "animals_weazle_sand shadow weazle" },
{ id: 11, name: "fruits" },
{ id: 32, name: "fruits_banana" },
{ id: 10, name: "threes" },
{ id: 15, name: "cars" }
],
tree = [];
obj.forEach(function (a) {
var path = a.name.split('_'),
o = {};
o.id = a.id;
path.reduce(function (r, b) {
o.name = b;
r.some(function (c) {
if (c.name === b) {
c.items = c.items || [];
r = c.items;
return true;
}
});
return r;
}, tree).push(o);
});
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');
Update: Version for independent order of items.
var obj = [
{ id: 5, name: "animals_weazle_sand shadow weazle" },
{ id: 32, name: "fruits_banana" },
{ id: 1, name: "animals" },
{ id: 2, name: "animals_cat" },
{ id: 3, name: "animals_dog" },
{ id: 4, name: "animals_weazle" },
{ id: 11, name: "fruits" },
{ id: 10, name: "threes" },
{ id: 15, name: "cars" },
{ id: 999, name: "music_pop_disco_euro"}
],
tree = [];
obj.forEach(function (item) {
var path = item.name.split('_'),
o = tree;
path.forEach(function (a, i) {
var oo = { name: a, items: [] },
last = path.length - 1 === i,
found = o.some(function (b) {
if (b.name === a) {
if (last) {
b.id = item.id;
return true;
}
b.items = b.items || [];
o = b.items;
return true;
}
});
if (!found) {
if (last) {
o.push({ id: item.id, name: a });
} else {
o.push(oo);
o = oo.items;
}
}
});
});
document.write('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');

Categories