This question already has answers here:
Remove array element based on object property
(12 answers)
Closed 3 years ago.
I want to remove some element in my array using splice method with if condition in my iteration. I do the following:
var list = [{type:"product",name:"Product A"},{type:"product",name:"Product B"},{type:"service", name:"Service A"},{type:"service", name:"Service B"}]
list.forEach(function (item, index) {
if (item.type == 'service'){
list.splice(index, 1)
}
}
//result: list = list = [{type:"product",name:"Product A"},{type:"product",name:"Product B"},{type:"service", name:"Service A"}]
//expected: list = [{type:"product",name:"Product A"},{type:"product",name:"Product B"}]
I expect the both element with type "service" will be removed, but only the first element is removed.
You can use Array.prototype.filter()
Code:
const list = [{type:"product",name:"Product A"},{type:"product",name:"Product B"},{type:"service", name:"Service A"},{type:"service", name:"Service B"}];
const resultList = list.filter(item => item.type !== 'service');
console.log(resultList);
When using forEach(), If the array is modified during iteration, other elements might be skipped
Why don't use Array.prototype.filter():
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
var list = [{type:"product",name:"Product A"},{type:"product",name:"Product B"},{type:"service", name:"Service A"},{type:"service", name:"Service B"}]
list = list.filter( item => item.type != 'service');
console.log(list);
Related
Consider this array of objects and array of items i want to filter the first array to include only the objects related to the names in Array but follows the order of Array and not the order of object
object= [{name:'ali', age:10},{name:'max', age:5},{name:'john', age:6},{name:'well',age:12}]
Array= ['max','well','john']
const filterit= object.filter(item=>{
if(Array.includes(item.name)
return item.name
})
console.log(filterit)
the output result is
[{name:'max', age:5},
{name:'john', age:6},
{name:'well',age:12}]
the filter works perfect and only the objects related to names in Array gets filtered the only problem is that it gets filtered according to their order in the 'object' array and not according to the names order in 'Array' so how to fix this in order to get a filtered array in the same order as in Array cause order is very crucial to me
First of all, this filter will not work as expected, as you return the item name, it will filter the items that have falsy value for name.
const filterit= object.filter(item=>{
if(Array.includes(item.name))
return item.name
})
You shouldn't return item.name, but it should return Array.includes(item.name)
const filterit= object.filter(item => Array.includes(item.name))
And to make the array with the same sorting.
let array = [{name:'ali', age:10},{name:'max', age:5},{name:'john', age:6},{name:'well',age:12}]
let sortedArray = []
let namesArray = ['max','well','john']
namesArray.forEach(name => {
let item = array.find(i => i.name === name)
if (item) sortedArray.push(item)
})
console.log(sortedArray)
Just iterate over the Array itself and filter that obj's array on match
consdt objArr = object= [{name:'ali', age:10},{name:'max', age:5},{name:'john', age:6},{name:'well',age:12}]
const myArr = ['max','well','john']
const result = myArr.filter(elem => {
return objArr.find(item => item.name == elem)
})
This question already has answers here:
The best way to remove duplicate strings in an array
(7 answers)
Remove Only One Duplicate from An Array
(6 answers)
Closed 1 year ago.
I have 2 apples in array. Filter method deletes all apples. Is there a way to delete only 1 of them.
var box = ['banana', 'apple', 'apple']
Output that I'm expectig:
box.filter((a) => a !== 'apple') => ['banana', 'apple']
Nothing built-in, no. You can remember whether you've seen it and always return true afterward:
const box = ["banana", "apple", "apple"];
let seenApple = false;
const filtered = box.filter((a) => {
if (seenApple) {
return true;
}
seenApple = a === "apple";
return !seenApple;
});
console.log(filtered);
Alternatively you could find the index of the first apple:
const appleIndex = box.findIndex(a => a === "apple");
...and then either filter by that index:
const filtered = box.filter((entry, index) => index !== appleIndex);
...or use splice to modify the array in-place.
Are you looking to remove duplicates?
If you just want an array with unique elements, you can do something like this
var unique_arr = arr.filter(function(elem, index, self) {
return index === self.indexOf(elem);
})
You could take a closure with another variable for overriding the condition.
const
box = ['banana', 'apple', 'apple'],
result = box.filter(
(found => a => a !== 'apple' || found || !(found = true))
(false)
);
console.log(result);
This question already has an answer here:
jQuery sort array value in sequence
(1 answer)
Closed 3 years ago.
Suppose I have an array like this:
let array = ["eid_x", "eid_x", "cid_x", "cid_x"]
how would I sort it so it's like this?
let array = ["cid_x", "eid_x", "cid_x", "eid_x"]
The original array is in a random order, example: eid, cid, cid, eid.
Does anyone know how this can be sorted like in the second array?
Split the items into two arrays then grab an item off of one alternating between the two arrays within your loop (or an Array#map in this case).
let array = ["eid_x", "eid_x", "cid_x", "cid_x"]
let eid = array.filter(i => i == 'eid_x')
let cid = array.filter(i => i == 'cid_x')
let result = new Array(array.length).fill(null)
.map((i, idx) => idx % 2 == 0 ? cid.shift() : eid.shift())
console.log(result)
This question already has answers here:
Remove array element based on object property
(12 answers)
Closed 4 years ago.
I have an array like this
var items = [{id:'1',token:'jj'},{id:'2',token:'kk'}];
I would like to delete an object from the array that matches id = 2
Here is my solution
//find the corresponding object
let obj=items.find((item) => item.id=='2');
//loop through the original and delete
Is there any other way to do this more efficiently??
I would like to suggest using splice, this doesn't change the reference of the existing array but just removes the desired element..
let items = [{id:'1',token:'jj'},{id:'2',token:'kk'}];
let indexToRemove = items.findIndex((eachElem) => {return eachElem.id == 2})
items.splice(indexToRemove, 1)
console.log(items)
Use Array#filter function for deleting item/s from the array. It actually returns a new array containing those items which corresponds to the predicate.
let items = [{id:'1',token:'jj'},{id:'2',token:'kk'}];
let filtered = items.filter(item => item.id !== '2');
console.log(filtered);
For removing from the original array
let items = [{id:'1',token:'jj'},{id:'2',token:'kk'}];
let index = items.findIndex(item => item.id === '2');
items.splice(index, 1);
console.log(items);
You can check the console :D
var items = [{id:'1',token:'jj'},{id:'2',token:'kk'}, {id:'4',token:'kk'}, {id:'2',token:'kl'}];
items.forEach(item =>{
if(item['id'] == '2') items.splice(items.indexOf(item),1)
})
console.log(items)
You can use splice() with forEach() too:
var items = [{id:'1',token:'jj'},{id:'2',token:'kk'}];
items.forEach((item, index) => {
if(item.id === '2'){
items.splice(index,1);
}
});
console.log(items);
I have an array of objects. I want to find by some field, and then to change it:
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
var foundItem = items.find(x => x.id == item.id);
foundItem = item;
I want it to change the original object. How? (I don't care if it will be in Lodash too.)
You can use findIndex to find the index in the array of the object and replace it as required:
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;
This assumes unique IDs. If your IDs are duplicated (as in your example), it's probably better if you use forEach:
items.forEach((element, index) => {
if(element.id === item.id) {
items[index] = item;
}
});
My best approach is:
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
items[items.findIndex(el => el.id === item.id)] = item;
Reference for findIndex
And in case you don't want to replace with new object, but instead to copy the fields of item, you can use Object.assign:
Object.assign(items[items.findIndex(el => el.id === item.id)], item)
as an alternative with .map():
Object.assign(items, items.map(el => el.id === item.id? item : el))
Functional approach:
Don't modify the array, use a new one, so you don't generate side effects
const updatedItems = items.map(el => el.id === item.id ? item : el)
Note
Properly used, references to objects are not lost, so you could even use the original object reference, instead of creating new ones.
const myArr = [{ id: 1 }, { id: 2 }, { id: 9 }];
const [a, b, c] = myArr;
// modify original reference will change object in the array
a.color = 'green';
console.log(myArr[0].color); // outputs 'green'
This issue usually happens when consuming lists from database and then mapping the list to generate HTML content which will modify the elements of the list, and then we need to update the list and send it back to database as a list.
Good news is, references are kept, so you could organize your code to get advantage of it, and think about a list as an Object with identities for free, which are integers from 0 to length -1. So every time you access any property of your Object, do it as list[i], and you don't lose reference, and original object is changed. Keep in mind that this is useful when your source of truth is only one (the Object created), and your app is always consistently consuming the same Object (not fetching several times from database and assigning it to list along the lifespan of the component).
Bad news is that the architecture is wrong, and you should receive an object by ids (dictionary) if this is what you need, something like
{
1232: { id: 1232, ...},
asdf234asf: { id: 'asdf234asf', ...},
...
}
This way, you don't search in arrays, which is resource consuming. You "just access by key in the object", which is instant and performant.
One-liner using spread operator.
const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));
An other approach is to use splice.
The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements in place.
N.B : In case you're working with reactive frameworks, it will update the "view", your array "knowing" you've updated it.
Answer :
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
let foundIndex = items.findIndex(element => element.id === item.id)
items.splice(foundIndex, 1, item)
And in case you want to only change a value of an item, you can use find function :
// Retrieve item and assign ref to updatedItem
let updatedItem = items.find((element) => { return element.id === item.id })
// Modify object property
updatedItem.aProp = ds.aProp
Given a changed object and an array:
const item = {...}
let items = [{id:2}, {id:3}, {id:4}];
Update the array with the new object by iterating over the array:
items = items.map(x => (x.id === item.id) ? item : x)
May be use Filter.
const list = [{id:0}, {id:1}, {id:2}];
let listCopy = [...list];
let filteredDataSource = listCopy.filter((item) => {
if (item.id === 1) {
item.id = 12345;
}
return item;
});
console.log(filteredDataSource);
Array [Object { id: 0 }, Object { id: 12345 }, Object { id: 2 }]
Whereas most of the existing answers are great, I would like to include an answer using a traditional for loop, which should also be considered here. The OP requests an answer which is ES5/ES6 compatible, and the traditional for loop applies :)
The problem with using array functions in this scenario, is that they don't mutate objects, but in this case, mutation is a requirement. The performance gain of using a traditional for loop is just a (huge) bonus.
const findThis = 2;
const items = [{id:1, ...}, {id:2, ...}, {id:3, ...}];
for (let i = 0, l = items.length; i < l; ++i) {
if (items[i].id === findThis) {
items[i].iAmChanged = true;
break;
}
}
Although I am a great fan of array functions, don't let them be the only tool in your toolbox. If the purpose is mutating the array, they are not the best fit.
I don't see this approach in the answers yet, so here's a simple little one liner
let item = {id: 1, new: true};
let items = [{id: 1}, {id: 2}];
let replaced = [item, ...items.filter(i => i.id !== item.id)]
You're just adding the item to the original array filtered of the item you're replacing.
worked for me
let returnPayments = [ ...this.payments ];
returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;
In my case, I wanted to find some element ( and its length) and wanted to add a new element no_of_agents in the object itself. So following did help me
details.forEach(obj => {
const length = obj["fleet_ids"].length || 0;
obj.set("no_of_agents" , length)
});
Somehow map() returned with other details(like '$__': InternalCache,
strictMode, shardval, etc) which was not required,
You can do like this too
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
var foundItem = items.filter((x) => x.id == item.id).pop();
foundItem = item;
OR
items.filter((x) => x.id == item.id).pop()=item;