Find JS object/hash with specific key-value pair - javascript

Suppose I have a JS object with multiple objects with the same properties.
EDIT: I modified the outer braces to square brackets to reflect what the actual object is. The accepted answer is in the comments.
var object = [
{
id: 1,
foo: 'bar'
},
{
id: 2,
foo: 'bar2'
},
{
id: 3,
foo: 'bar3'
},
{
id: 4,
foo: 'bar4'
}
];
How would I get the object with a specific id e.g. id == 1, something similar to the Rails method ActiveRecord::Relation.where(id: 1)?

You need to make an array of objects for search and try this like,
var object = [{ // make array by using [ and ]
id: 1,
foo: 'bar'
}, {
id: 2,
foo: 'bar2'
}, {
id: 3,
foo: 'bar3'
}, {
id: 4,
foo: 'bar4'
}];
function searchByKey(obj, key) {
for (var i in obj) {
if (obj[i].id == key) {
return obj[i];
}
}
return "Not found";
}
console.log(searchByKey(object,1));
console.log(searchByKey(object,4));
Live Demo

Related

Javascript spread on array index to 'push' new item to nested array

Consider the following data:
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
];
I'm trying to push something to the nested bar array on index 1 using the spread syntax (...).
So the final array should become:
[
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, 'new-item' ] }
]
Normally, we'll just use push: data[1].bar.push(0), but I need a spread solution
I've tried to use this approach:
How to push new elements to a nested array of objects in JavaScript using spread syntax
data = [ ...data, {[1]: { ...data[1], bar: [ ...data[1].bar, 'new-item' ] } }]
But this will append another object with a single key 1, it does not alter data[1].
Then, I've tried to use Object.assign() but again ended up with a new index:
Replace array entry with spread syntax in one line of code?
data = [ ...data, Object.assign({}, data[1], { bar }})
tl;dr, How do I append something to an array, part of an object, that's inside an array of objects, using the spread syntax?
Please link me to a duplicate, or provide a way to do this
Playground:
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9 ] }
];
// 'Regular' push method
// data[1].bar.push(0);
// Using spread reassign
// data = [ ...data, {[1]: { ...data[1], bar: [ ...data[1].bar, 'new-item' ] } }]
// Using Object.assign
data = [ ...data, Object.assign({}, data[1], {bar: [ 'new-item' ] } ) ];
console.log(data)
You could take an outer Object.assign with an array as target and an object with the index as key.
let
data = [
{ foo: true, bar: [1, 2, 3] },
{ foo: true, bar: [8, 9] }
];
data = Object.assign(
[...data], // target array
{ 1: { // array index as key
...data[1],
bar: [...data[1].bar, 'new-item']
} }
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Object.assign on the array itself.
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
];
data = Object.assign([...data], {1: { ...data[1], bar: [...data[1].bar, 'new-item']}});
console.log(data);
I don't think this is more readable than many other options open to you but this satisfies the requirement of "using object spread".
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] },
{ foo: false, bar: [ ] }
];
let idx = 1;
let newData = [
...data.slice(0, idx),
{
...data[idx],
bar: [ ...data[idx].bar, 'new-item' ]
},
...data.slice(idx+1)
];
console.log(newData);
This will first take your data and cut the array up to the item you wish to replace (index 1). A new object follows, then the rest of the array (if any) follows.
First, treat the array like an object with numbered keys, and use the spread operator and override the necessary index. Then, use Object.values() to treat it like an array.
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
]
data = Object.values({ ...data, 1: { ...data[1], bar: [ ...data[1].bar, 'new-item' ] } })
console.log(data)
In this particular case, if the index you need to alter is near the beginning of the array, you can also use an IIFE to allow for a destructuring approach, like this:
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
]
data = (([first, {bar, ...rest}]) => [first, {...rest, bar:[...bar, 'new-item']}])(data)
console.log(data)
You can just assign the first element index to the modified element that uses Array#map and the spread operator as follows:
const data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
];
data[1] = [data[1]].map(({foo,bar}) => ({foo,bar:[...bar,"some new value"]}))[0];
console.log( data );

how to add object value after filter in javascript

How to add object value after filter out javascript
var arr = [{
id: 1,
username: 'fred'
}, {
id: 2,
username: 'bill'
}, {
id: 3,
username: 'ted'
}];
var obj = {
id: 3,
online: true
}
const result = arr.filter((item) => {
if (item.id === obj.id) {
return {
item,
online: obj.online
}
}
})
console.log(result)
It should be
{
id: 3,
username: "ted",
online: true
}
Set item.online inside filter method.
var arr = [{
id: 1,
username: 'fred'
}, {
id: 2,
username: 'bill'
}, {
id: 3,
username: 'ted'
}];
var obj = {
id: 3,
online: true
}
const result = arr.filter((item) => {
if (item.id === obj.id) {
item.online = obj.online;
return true;
}
})
console.log(result)
The OP expected output is a single object. filter() returns an array. find() finds the first object meeting the criterion returned by the predicate function. It's poor style for the predicate function to have a side-effect.
find() the object, then modify it.
const arr = [{
id: 1,
username: 'fred'
}, {
id: 2,
username: 'bill'
}, {
id: 3,
username: 'ted'
}];
var obj = {
id: 93,
online: true
}
const result = arr.find(item => item.id === obj.id)
result ? result.online = true : null
console.log(result)
According to this problem, Object.assign() is more suitable to solve this problem. One by one value assignment creates many boilerplate, needs more effort.
The Object.assign() method copies all enumerable own properties from one or more source objects to a target object. It returns the target object.
Properties in the target object are overwritten by properties in the sources if they have the same key. Later sources' properties overwrite earlier ones.
Code block:
var arr = [{
id: 1,
username: 'fred'
}, {
id: 2,
username: 'bill'
}, {
id: 3,
username: 'ted'
}];
var obj = {
id: 3,
online: true
}
function mergeObjByID(item) {
if (item.id === obj.id){
//overwrite item value
Object.assign(item,obj)
return true
}
}
const result = arr.filter(mergeObjByID);
console.log(result)
More about Object.assign() example:
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

Lodash, find every object given an array of ids

What I have works, but I have a suspicion that there is a lodash method that can do this without the _.map().
const _ = require('lodash')
const ids = [1, 2]
const objects = [
{
id: 1,
foo: 'bar'
}, {
id: 2,
foo: 'baz'
}, {
id: 3,
foo: 'quux'
}
]
const result = _.map(ids, id => _.find(objects, { id }))
console.log(result)
// => [ { id: 1, foo: 'bar' }, { id: 2, foo: 'baz' } ]
Thanks!
You can use _.intersectionWith() to get items from the objects array, which id is equal to an item in the ids array:
const ids = [1, 2]
const objects = [{ id: 1, foo: 'bar' }, { id: 2, foo: 'baz' }, { id: 3, foo: 'quux' }]
const result = _.intersectionWith(objects, ids, (o, id) => o.id === id)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
Another option is to convert the objects array to a object of { [id]: obj } using _.keyBy() (the id), and then using _.at() to get the items from the dictionary using _.at():
const ids = [1, 2]
const objects = [{ id: 1, foo: 'bar' }, { id: 2, foo: 'baz' }, { id: 3, foo: 'quux' }]
const result = _.at(_.keyBy(objects, 'id'), ids)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

Immutable.js algorithm: List.update_or_add(item)

I want to concatenate 2 lists in immutable.js.
Both lists have this structure: { id, value }
The algorithm concatenate should do this:
If an ID exists in both list1 and list2 take the value from list2.
let list1 = [
{ id: 1, value: 'foo' },
{ id: 3, value: 'bar' },
{ id: 2, value: 'baz' },
]
let list2 = [
{ id: 1, value: 'quux' }, // id 1 exists in list1
{ id: 4, value: 'asd' },
]
let result = [
{ id: 1, value: 'quux' }, // from list 2
{ id: 3, value: 'bar' },
{ id: 2, value: 'baz' },
{ id: 4, value: 'asd' },
]
If Immutable.js has this functionality with another type (eg. Dictionary), I could also use that.
Algorithms for union
First you have to maintain two map with key as id and value as object then check for length of array which is of bigger size and pass the bigger size array with small size map to merged function there you can iterate over the array and check if it's exists in the map if yes then update the object and delete that row from map otherwise add the object into output. After the for loop complete check if map has element present then push all the values from map into output array and return;
index.js
const old = [
{ id: 1, value: 'foo' },
{ id: 3, value: 'bar' },
{ id: 2, value: 'baz' },
];
const newa = [
{ id: 1, value: 'quux' }, // update
{ id: 4, value: 'asd' }, // push
];
function merged(input,filterMap){
var output = [];
input.forEach(function(eachRow){
if(filterMap.hasOwnProperty(eachRow.id)){
output.push(Object.assign(eachRow,filterMap[eachRow.id]));
delete filterMap[eachRow.id];
}else{
output.push(eachRow);
}
});
if(Object.keys(filterMap).length > 0){
output = output.concat(Object.values(filterMap));
}
return output;
}
function parseData(first,second){
var mapFirst = {},
mapSecond = {};
var output = [];
first.forEach(function(eachRow){
mapFirst[eachRow.id] = eachRow;
});
second.forEach(function(eachRow){
mapSecond[eachRow.id] = eachRow;
});
if(first.length > second.length){
return merged(first,mapSecond);
}else{
return merged(second,mapFirst);
}
}
console.log(parseData(old,newa));
Working jsFiddle demo - https://jsfiddle.net/qz25hnmf/

Find and update an object in an array

I want to get an object from an array of objects, then update it.
var myObjs = [{ id: 1, name: "foo"}, { id: 2, name: "bar" }];
var myObjectToUpdate = _.findWhere(myObjs, { id: 2 });
myObjectToUpdate = { id: 2, name: "boop" };
myObjs[1] // { id: 2, name: "boop" }
Currently when I update myObject in the 3rd line, it does not update the array of objects. I'm assuming it is updating the new variable instead of referencing.
What is the correct way to do this?
#E_net4 is correct, you are reassigning the object you just found.
If all you need to do is update the name, try this:
var myObjs = [{ id: 1, name: "foo"}, { id: 2, name: "bar" }];
var myObjectToUpdate = _.findWhere(myObjs, { id: 2 });
myObjectToUpdate.name = "boop";
myObjs[1] // { id: 2, name: "boop" }
I guess this is what you want. You have, in your code, misconceptions. Please read my code and compare both.
Hope it helps!
function fn(arr, toReplace, newValue) {
for(var x in arr) {
for(var k in toReplace) {
if(arr[x][k] == toReplace[k]) {
arr[x] = newValue;
}
}
}
return arr;
};
var arr = [{ id: 1, name: "foo"}, { id: 2, name: "bar" }];
var newValue = {id: 2, name: "boop"};
arr = fn(arr, {id: 2}, newValue);
console.log(arr);

Categories