nodesData=[
{name:'name1'},
{name:'name2'},
{name:'name1'},
{name:'name3'},
]
uniqData=[
{name:'name1'}
{name:'name2'}
{name:'name3'}
]
for (let i = 0; i < nodesData.length; i += 2) {
const currentSource = nodesData[i];
const currentTarget = nodesData[i + 1];
const currentData = {
source: uniqData.indexOf(currentSource),
target: uniqData.indexOf(currentTarget),
};
}
So I've got two lists with objects. First list is list with objects that contains names, and other list is list generated with function that I've made for removing duplicates.The problem is when I use for loop and loop through nodesData list only the first time I get only for source index of -1...why? and other indexOf work expected.
So the console.log would be:
source:-1, target:1
source:0, target:2
The objects in the array have differents references even if they looks like they are the same. Basically :
console.log({name: 'name1'} === {name: 'name1'}); // false
It prints false because the compared objects haven't the same references even if they are similar.
So in your example the indexOf method returns -1 because the objects have not the same reference (again even if they looks like they are equal).
Since you can't directly use indexOf you have to first get the object's reference with find and then you can use indexOf, like this :
const nodesData=[
{name:'name1'},
{name:'name2'},
{name:'name1'},
{name:'name3'},
]
const uniqData=[
{name:'name1'},
{name:'name2'},
{name:'name3'},
]
for (let i = 0; i < nodesData.length; i += 2) {
const currentSource = nodesData[i];
const currentTarget = nodesData[i + 1];
const currentData = {
source: uniqData.indexOf(uniqData.find(({name}) => name === currentSource.name)),
target: uniqData.indexOf(uniqData.find(({name}) => name === currentTarget.name)),
};
console.log(currentData);
}
Note :
I used destructuring in order to directly get the name property
Here is what I have tried so far but I am only getting 1 value in return.
Object.keys(yelpResults).map((key) => {
return setRestaurantIndexes(restaurantIndexes.concat(key));
});
The function Object.keys alone do the trick, it returns an array with the names of the properties and methods of an object.
const data = {
name: 'John Doe',
age: 50,
country: 'NZ'
}
const propertyNames = Object.keys(data)
console.log(propertyNames);
// prints: ['name', 'age', 'country']
First make your object.
const result = ["Apple", "Orange", "Plum"];
Then declare an array where you will save your index values
let newArray = []
Then loop through the object created at step 1.
//loop the results
for(var i=0, l=result.length; i < l; i++){
//push the object's index to the array
newArray.push(i);
}
Console Log your new array with index values saved in it.
console.log(newArray);
you can refer this example if it helps.
Map function can be executed on array , so first we need to convert object into array and then execute operation on it.
const details={
name:'John',
lName:'lee',
country:'US'
}
const getIndex = Object.keys(details).map((item , i)=>{
return i;
});
console.log(getIndex);
I wanted to optimize my code removing a for-loop.
groupFieldNames = [];
for (i = 0; i < data.length; i++) {
groupFieldNames.push(data[i].groupFieldName);
}
data is an array of objects, each having 4 fields.
I am interested in the one identified as groupFieldName.
Is there a way to avoid the loop and directly push the fields in the array?
EDIT:
I went with #Yosvel Quintero suggestion (to all the guys suggesting the map solution, he was the first one), and checked the performance.
With a data array having ~60k objects I've got:
3ms using map;
11ms using for-loop
Not bad.
You can use Array.prototype.map()
const groupFieldNames = [];
for (i = 0; i < data.length; i++) {
groupFieldNames.push(data[i].groupFieldName);
}
To:
const groupFieldNames = data.map(o => o.groupFieldName);
You could effectively use Array's built-in .map() here as follows -
var data = [
{ id: 1, groupFieldName: 'abcd' },
{ id: 2, groupFieldName: 'pars' }
];
var groupFieldNames = data.map(obj => obj.groupFieldName)
console.log(groupFieldNames);
You can use map
var groupFieldNames = [];
var data=[{groupFieldName:'a'},{groupFieldName:'b'},{groupFieldName:'c'}]
console.log(data.map(x=>x.groupFieldName))
You can also use forEach
var groupFieldNames = [];
var data=[{groupFieldName:'a'},{groupFieldName:'b'},{groupFieldName:'c'}]
data.forEach(x=>groupFieldNames.push(x.groupFieldName))
console.log(groupFieldNames)
You can use Array.prototype.map() with Destructuring assignment in the following way:
const data = [
{id: 66, groupFieldName: 'test', other: 'other'},
{id: 66, groupFieldName: 'test2', other: 'other2'}
];
const groupFieldNames = data.map(({groupFieldName}) => groupFieldName);
console.log(groupFieldNames);
var arrayA = [ {"name":"sachin","location":"mum"} ];
var arrayB = [ {"name":"Ganguly","location":"mum"} ];
var newArray = arrayA.push(JSON.stringify((arrayB[0].name)));
console.log(newArray); console.log(arrayA);`
if you dont want to create new array then:
var arrayA = [ {"name":"sachin","location":"mum"} ];
var arrayB = [ {"name":"Ganguly","location":"mum"} ];
arrayA[0].name = arrayB[0].name;
console.log(arrayA);`
Since it's an object array and assuming more than one element in future, you need to filter out ganguly object and add it to newArray, and to remove sachin object, you can use the same filter function.
var gangulyArr = arrayB.filter(function(el) {
return el.name === "Ganguly";
});
var newArray = arrayA.concat(gangulyArr);//gangulyArr has all objs named
// ganguly, even if its one
arrayA = arrayA.filter(function(el) {
return el.name !== "sachin"; // to remove sachin from original array
});
If you want to write less code, prefer underscore, it has great methods for these - find, remove, reject, pluck etc.,
var gangulyObj = _.find(arrayB, 'name', 'Ganguly');
var newArray = arrayA;
if(gangulyObj) {
newArray.push(gangulyObj);
}
arrayA = _.reject(arrayA , function(el) { return el.name === "sachin"; });
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;