So this is how my data looks:
categories = [
{
name: ""
products: [
{
id: 1,
...
},
{
id: 2,
...
}
]
},
{
name: ""
products: [
{
id: 3,
...
},
{
id: 4,
...
}
]
},
...
]
I want to remove a product with id 1 and this is my code:
categories.map(category => category.products.filter(product => product.id !== 1))
Is this the right code? If so how I create a new array and set it with the new values?
You're close, but your code is replacing category objects with just their filtered products array, losing the rest of the object properties. You need to copy each category object as well as its products array, which you typically do via spread notation:
updatedCategories = categories.map(category => ({
...category,
products: category.products.filter(product => product.id !== 1)
}));
Just a modified version on T.J. Crowder's response.
The filterGroupedBy function is more versatile and de-coupled from the business logic.
I even created a lodash mixin that you can call via:
_.filterGroupedBy(list, key, fn) or_.chain(list).filterGroupedBy(key, fn).value()const disp = (value) => console.log(JSON.stringify(value))
const filterGroupedBy = (list, key, fn) =>
list.map(item => ({
...item,
[key] : item[key].filter(entry => fn(entry))
}))
_.mixin({
'filterGroupedBy' : (list, key, fn) => filterGroupedBy(list, key, fn)
})
let categories = [{
name: "",
products: [{ id: 1 }, { id: 2 }]
}, {
name: "",
products: [{ id: 3 }, { id: 4 }]
}]
// plain js
disp(filterGroupedBy(categories, 'products', (prod) => prod.id !== 1))
// lodash - static and chain
disp(_.filterGroupedBy(categories, 'products', (prod) => prod.id !== 1))
disp(_.chain(categories).filterGroupedBy('products', (prod) => prod.id !== 1).value())
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
If you have nested data, you can iterate through a path to target the object you want to filter on.
You just need a function similar to Object.byPath (a custom polyfill).
const main = () => {
let categories = [{
name: "",
products: {
data : [{ id: 1 }, { id: 2 }]
}
}, {
name: "",
products: {
data : [{ id: 3 }, { id: 4 }]
}
}]
// plain js
disp(filterGroupedBy(categories, 'products.data', p => p.id !== 1))
// lodash - static and chain
disp(_.filterGroupedBy(categories, 'products.data', p => p.id !== 1))
disp(_.chain(categories).filterGroupedBy('products.data', p => p.id !== 1).value())
}
// Required by filterGroupedBy
if (Object.byPath === undefined) {
Object.byPath = (obj, path) => path
.replace(/\[(\w+)\]/g, '.$1')
.replace(/^\./, '')
.split(/\./g)
.reduce((ref, key) => key in ref ? ref[key] : ref, obj)
}
/* #ifndef filterGroupedBy */
const filterGroupedBy = (list, path, fn) =>
list.map(item => {
let lastIndex = path.lastIndexOf('.'),
target = path.substring(0, lastIndex),
key = path.substring(lastIndex + 1)
return Object.assign({}, Object.byPath(item, target), {
[key] : Object.byPath(item, path).filter(entry => fn(entry))
})
})
_.mixin({
'filterGroupedBy' : (list, key, fn) => filterGroupedBy(list, key, fn)
})
/* #endif */
const disp = (value) => console.log(JSON.stringify(value))
main()
.as-console-wrapper { top: 0; max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With