Having the following nested array of objects:
[
{
"items": [
{
"name": "See data",
"href": "/data",
},
{
"name": "Account",
"href": "/account",
"icon": {}
}
]
},
{
"items": [
{
"name": "name",
"href": "/name",
"icon": {}
},
{
"name": "My Rooms",
"href": "/rooms",
"icon": {}
}
]
},
{
"items": [
{
"name": "user",
"href": "/user",
"icon": {}
}
]
}
]
How it's possible to remove an inside object by name?
For example to remove the object with name "Account"?
A solution that works is delete myData[0].items[1]; but it's kind of hardcoded.
Also tried like:
myData[0].items = myData[0].items.filter(function (item) {
return item.name !== 'Account';
});
You can use splice to change the original array in-place and findIndex to find the index of the item to remove.
for (const {items} of data) {
const i = items.findIndex(({name}) => name === 'Account');
if (i > -1) items.splice(i, 1);
}
Related
This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 4 months ago.
If the 'id' key is duplicated among the objects in the array, how to delete the object
I tried using filter, map, and set, but it doesn't work.
It's not a one-dimensional array, so I don't know how to do it.
as-is
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
to-be
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
We iterate over that list using reduce function, then we checked whether the key we are accessing is visited or not with keys parameter of reduce method, and if it's not visited then we just push that object to a filtered array and returning keys array to keep it updated.
const data = {
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let filtered = [];
data.category.list.reduce((keys, currentObject) => {
if (!keys.includes(currentObject.id)) { //checking if current oject id is present in keys or not
// if not present than we will just push that object in
keys.push(currentObject.id);
//getting filttered object
filtered.push(currentObject);
}
return keys; //returning keys to update it
}, [])
data.category.list = filtered; //updating list
console.log(data);
A solution based on #Nick's comment
let data ={
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let uniq = data.category.list.filter((o,i,a) => a.findIndex(o2 => o2.id == o.id) == i)
data.category.list = uniq
console.log(data)
You can use a set to track if id
const category = [{
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345",
},
{
"id": "12345",
},
{
"id": "67890",
},
]
}
}]
const z = category.map(elem => {
const set = new Set()
return {
...elem,
category: {
...elem.category,
list: elem.category.list.reduce((acc, curr) => {
if (!set.has(curr.id)) {
set.add(curr.id);
acc.push(curr)
}
return acc;
}, [])
}
}
});
console.log(z)
I'm trying to filter everything inside 'items' with 'name': "", without losing structure and values of fieldLabel and placeholder. Below is my current object:
result: {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
"name": ""
},
{
"name": ""
}
]
}
I want the object to look like this after filtering:
result: {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
]
}
Have a reference to the original object first.
const results = {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
}
Create a new object from the reference. Use spread syntax for copying object. Then filter method for filtering
const newObject = {
...results,
items: results.items.filter(item => item.name)
}
You can filter the nested items array that have truthy name properties.
const result= {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
};
result.items = result.items.filter(({ name }) => name);
console.log(result);
If you need to do this using an immutable pattern then shallow copy the object and nested properties that you are updating.
const result= {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
};
const newresult = {
...result,
items: result.items.filter(({ name }) => name)
};
console.log(newresult);
console.log(result === newresult); // false since new object
Something like this?
Filter YOUROBJ.items to keep all entries where property name has a value that is not null/undefined/false
res.items = res.items.filter(e => e.name);
const obj = {
"fieldLabel": "foo",
"placeholder": "foo",
"items": [
{
"name": "foobar"
},
{
"name": ""
},
{
"name": ""
}
]
}
const res = Object.assign({}, obj); // copy object to not mutate the original one
res.items = res.items.filter(e => e.name); // filter array "items" to just keep items with property name
console.log(res);
I have an object like this:
var data = [
{"id":"36e1e015d703120058c92cf65e6103eb","title":"Alex McGibbon"},
{"id":"60beb5e7d7600200e5982cf65e6103ad","title":"Alex Linde"},
{"subs":[{"id":"62826bf03710200044e0bfc8bcbe5df1","title":"Abel Tuter"}],"id":"63e8479fdb161300bde15901cf96191c","title":"Abdul Waheed"},
{"subs":[{"subs":[{"id":"12826bf03710200044e0bfc8bcbe5db1","title":"Alfonso Griglen"},{"subs":[{"id":"06826bf03710200044e0bfc8bcbe5d8a","title":"Allyson Gillispie"},{"id":"b282abf03710200044e0bfc8bcbe5d28","title":"Allan Schwantd"}],"id":"22826bf03710200044e0bfc8bcbe5dec","title":"Alejandra Prenatt"}],"id":"0a826bf03710200044e0bfc8bcbe5d7a","title":"Adela Cervantsz"},{"id":"4847c4d4d773020058c92cf65e61038e","title":"Alisa Chinoy"},{"id":"71826bf03710200044e0bfc8bcbe5d3b","title":"Aileen Mottern "},{"id":"a8f98bb0eb32010045e1a5115206fe3a","title":"Abraham Lincoln"}],"id":"7c2e6109dbd65300bde15901cf9619b5","title":"Raju Koyagura"}
];
console.log(data)
Now I want to retrieve all the id values as a new array without consideration of which nested level it is.
My expected result is something like this::
var result = ['36e1e015d703120058c92cf65e6103eb','60beb5e7d7600200e5982cf65e6103ad','62826bf03710200044e0bfc8bcbe5df1','06826bf03710200044e0bfc8bcbe5d8a','b282abf03710200044e0bfc8bcbe5d28','22826bf03710200044e0bfc8bcbe5dec','0a826bf03710200044e0bfc8bcbe5d7a','4847c4d4d773020058c92cf65e61038e','71826bf03710200044e0bfc8bcbe5d3b','a8f98bb0eb32010045e1a5115206fe3a','7c2e6109dbd65300bde15901cf9619b5'];
console.log(result);
I am not getting any idea how to achieve it.?
You can use JSON.stringify to walk on the tree easily:
const ids = [];
JSON.stringify(data, (key, value) => {
if (key === 'id') ids.push(value);
return value;
});
Create a recursive function and check if that object have a key by id. Push the value of id. If the key is another array then call the same function with new value
var data = [{
"id": "36e1e015d703120058c92cf65e6103eb",
"title": "Alex McGibbon"
},
{
"id": "60beb5e7d7600200e5982cf65e6103ad",
"title": "Alex Linde"
},
{
"subs": [{
"id": "62826bf03710200044e0bfc8bcbe5df1",
"title": "Abel Tuter"
}],
"id": "63e8479fdb161300bde15901cf96191c",
"title": "Abdul Waheed"
},
{
"subs": [{
"subs": [{
"id": "12826bf03710200044e0bfc8bcbe5db1",
"title": "Alfonso Griglen"
}, {
"subs": [{
"id": "06826bf03710200044e0bfc8bcbe5d8a",
"title": "Allyson Gillispie"
}, {
"id": "b282abf03710200044e0bfc8bcbe5d28",
"title": "Allan Schwantd"
}],
"id": "22826bf03710200044e0bfc8bcbe5dec",
"title": "Alejandra Prenatt"
}],
"id": "0a826bf03710200044e0bfc8bcbe5d7a",
"title": "Adela Cervantsz"
}, {
"id": "4847c4d4d773020058c92cf65e61038e",
"title": "Alisa Chinoy"
}, {
"id": "71826bf03710200044e0bfc8bcbe5d3b",
"title": "Aileen Mottern "
}, {
"id": "a8f98bb0eb32010045e1a5115206fe3a",
"title": "Abraham Lincoln"
}],
"id": "7c2e6109dbd65300bde15901cf9619b5",
"title": "Raju Koyagura"
}
];
let newArray = [];
function getAllId(arr, key) {
arr.forEach(function(item) {
for (let keys in item) {
if (keys === key) {
newArray.push(item[key])
} else if (Array.isArray(item[keys])) {
getAllId(item[keys], key)
}
}
})
}
getAllId(data, 'id')
console.log(newArray)
I am trying to iterate through below Collections JSON object. I am trying to find collection elements which have one of the tags from tagArray. Basically this is a filter exercise to have collection elements that have tags as selected from the tagArray.
{
1: {
"description": "AAA",
"tags": [
{
"name": "tag1",
},
{
"name": "tag2",
},
{
"name": "tag3",
},
],
"name": "XYZ",
},
2: {
"description": "BBB",
"tags": [
{
"name": "tag1",
}
],
"name": "CCC",
},
3: {
"description": "xms",
"tags": [],
"name": "Huo",
},
4: {
"description": "asd",
"tags": [],
"name": "TXS",
}
}
tagArray looks like this : [ tag1, tag2, ... ]
I have coded it as below using lodash and it works fine. But I am not sure if I can improve this further and how?
const filterByTags = (collections, filterTags) => {
let filteredCollections = _.pickBy(collections, (collection) => {
let collectionWithTag = false;
_.map(collection.tags, (collectionTag) => {
if (filterTags.indexOf(collectionTag.name) !== -1) {
collectionWithTag = true;
return collectionWithTag;
}
});
return collectionWithTag;
});
return filteredCollections;
};
You don't want to use pickBy but rather filter (Lodash/native)
You don't want to use map but rather some (Lodash/native)
You don't want to use indexOf but rather includes (Lodash/native)
function filterByTags(collections, filterTags) {
return _.filter(collections, collection => {
return _.some(collection.tags, collectionTag => {
return _.includes(filterTags, collectionTag.name);
});
});
}
I have a JavaScript object which looks like this:
{
"filters": [
{
"name": "Test",
"items": [
{
"id": 1207700620,
"checked": false
},
{
"id": 1207825584,
"checked": false
},
{
"id": 1207969166,
"checked": true
}
]
},
{
"name": "Empty",
"items": []
},
{
"name": "ThirdList",
"items": [
{
"id": "1207828314",
"checked": true
},
{
"id": "1236723086",
"checked": false
},
{
"id": "1208005603",
"checked": true
}
]
}
]
}
My object have a array by the name filters. This array contains multiple objects. Within each object there is an array by name items. For each element in this items array, I need to check the checked property & if it is false, I need to delete that record (that item in items array).
I need to ensure IE 8 compatability.
I can use a for loop on filters array and within this for loop I can use another for loop to go over items array. I dont want this apporach.
Is there smarter way to achieve this by lodash or jquery or any other JavaScript library??
You can try a combination of forEach and filter methods:
obj.filters.forEach(function(filter) {
filter.items = filter.items.filter(function(el) {
return el.checked;
});
});
Check example below.
var obj = {
"filters": [
{
"name": "Test",
"items": [
{
"id": 1207700620,
"checked": false
},
{
"id": 1207825584,
"checked": false
},
{
"id": 1207969166,
"checked": true
}
]
},
{
"name": "Empty",
"items": []
},
{
"name": "ThirdList",
"items": [
{
"id": "1207828314",
"checked": true
},
{
"id": "1236723086",
"checked": false
},
{
"id": "1208005603",
"checked": true
}
]
}
]
};
obj.filters.forEach(function(filter) {
filter.items = filter.items.filter(function(el) {
return el.checked;
});
});
alert( JSON.stringify(obj, null, 4) );
For IE8 compatibility you can use polyfills or ES5 shims.
Another option if you can use Underscore/Lo-Dash, you can go with analog methods: _.each and _.filter instead of Array.prototype.forEach and Array.prototype.filter:
_.each(obj.filters, function(filter) {
filter.items = _.filter(filter.items, function(el) {
return el.checked;
});
});