Array to object with based on given key - javascript

I have an array declared which uses the Object.assign:
var obj = [{
id: 1,
value: 'abc'
}, {
id: 2,
value: 'xyz'
}];
console.log(Object.assign({}, obj));
it's getting transformed as,
{
'0': { id: 1, value: 'abc' },
'1': { id: 2, value: 'xyz' }
}
However I need to have this as, (here the 1 and 2 represents the id attribute of my object)
{
'1': {id: 1, value: 'abc'},
'2': {id: 2, value: 'xyz'}
}
I've tried few, but had no luck, Can someone shed some light?

You could map the objects in an object with the wanted key and assign it to a single object.
var objects = [{ id: 1, value: 'abc' }, { id: 2, value: 'xyz' }],
result = Object.assign(...objects.map(o => ({ [o.id]: o })));
console.log(result);

You can use reduce() method with Object.assign.
var obj = [{id: 1, value: 'abc'}, {id: 2, value: 'xyz'}];
var result = obj.reduce((r, e) => Object.assign(r, {[e.id]: e}), {});
console.log(result)

You can directly use Array#reduce to do that, and there is no need for Object.assign here:
var obj = [{id: 1, value: 'abc'}, {id: 2, value: 'xyz'}];
let result = obj.reduce((acc, item) => {
acc[item.id] = item;
return acc;
}, {});
console.log(result);

If you want to use .id to be the key, you can use reduce and use Object.assign
let obj = [{id: 1,value: 'abc'}, {id: 2,value: 'xyz'}];
let result = obj.reduce((c, v) => Object.assign(c, {[v.id]: v}), {});
console.log(result);

Related

Sort 2 objects with the same key Javascript

I have 2 objects where I want the second one to be in the same order as the first one.
Ex:
const obj1 = [
{ key: 1, id: 1, name: "John" },
{ key: 2, id: 2, name: "Ann" },
{ key: 3, id: 3, name: "Kate" }
];
const obj2 = [
{ key: 2, id: 2, name: "Ann" },
{ key: 1, id: 1, name: "John" },
{ key: 3, id: 3, name: "Kate" }
];
The purpose is to have obj2 in same order as obj1, but only sort with keys. I'm trying to make an helper function which will pass 3 argument:
function helper(obj1, obj2, key) {
// return new object with sorted array do not modify existing
}
I can sort one of this, but cant combine 2object together
My idea is to use hash map to store key obj2, then loop through key obj1 to sort obj2
const obj1 = [
{key: 1, id: 5, name: 'John'},
{key: 2, id: 5, name: 'John'},
{key: 3, id: 5, name: 'John'}
]
const obj2 = [
{key: 2, id: 5, name: 'John'},
{key: 1, id: 5, name: 'John'},
{key: 3, id: 5, name: 'John'}
]
function help(obj1, obj2, key) {
const hashKeyObj2 = obj2.reduce((val, item) => {
val[item[key]] = item;
return val;
}, {});
return obj1.map((item) => hashKeyObj2[item[key]]);
}
console.log(help(obj1, obj2, 'key'))
One-liner
let sorted = obj1.map(a => obj2.find(b => a.key === b.key))
This snippet will sort obj2 from obj1 order:
const obj1 = [
{ key: 1, id: 5, name: 'John' },
{ key: 3, id: 5, name: 'John' },
{ key: 2, id: 5, name: 'John' },
]
const obj2 = [
{ key: 2, id: 5, name: 'John' },
{ key: 1, id: 5, name: 'Jane' },
{ key: 3, id: 5, name: 'Tom' },
]
function helper(obj1, obj2, key) {
const findIndex = (refValue) => obj1.findIndex((candidate) => candidate[key] === refValue)
const comparator = (item1, item2) => findIndex(item1[key]) - findIndex(item2[key])
return [...obj2].sort(comparator)
}
const result = helper(obj1, obj2, 'key')
console.log('result :', result)
An Approach using lodash
function sortArrayBasedOnKeys(
array1: Record<string, number | string>[],
array2: Record<string, number | string>[],
key: string
) {
const order = _.map(array1, key);
return _.sortBy(array2, (item) => _.indexOf(order, item[key]));
}
First we are getting order in which objects in the array1 are placed and then using that order to sort the next array.

Delete multiple objects in an array by id

I have a main array of objects with each object having some key/values as well as a "id" key with 1,2,3,4,5, etc
Now I have another array representing just id's (like [2,3])
I want to use this array to delete objects from the main array...so in this case, objects from the main array having id's 2 & 3 should be deleted
While I am aware of findBy(id), I am not sure if that can be used to delete multiple objects at once.
You can use filter. In the filter callback function check if the id is also there in id array by using includes
let idArr = [1, 2]
let obj = [{
id: 1,
name: 'abc'
},
{
id: 2,
name: 'abc'
},
{
id: 3,
name: 'abc'
},
{
id: 4,
name: 'abc'
}
];
let data = obj.filter(item => !idArr.includes(item.id));
console.log(data);
console.log(obj)
using filter might work well here. you could write something like:
var newArray = oldArray.filter(object => !ids.includes(object.id))
You can do it, like this:
[2,3].forEach(key => {
delete object[key];
})
You can use filter method for this.
Ex:
let id = 2;
let list = [{
Id: 1,
Name: 'a'
}, {
Id: 2,
Name: 'b'
}, {
Id: 3,
Name: 'c'
}];
let lists = list.filter(x => {
return x.Id != id;
})
console.log(lists);
Assuming you want to delete items from the original array by entirely removing the element from the array (and you don't want to get a new array), you can take advantage of
Array.splice
let idArr = [1, 2];
let obj = [{
id: 1
},
{
id: 2
},
{
id: 3
},
{
id: 4
}
];
for (let id of idArr) {
// look for the element by its id.
const objIdRef = obj.find(i => i.id === id);
// if it actually exists, splice it.
objIdRef && obj.splice(obj.indexOf(objIdRef), 1);
}
console.log(obj);
If the obj array is big, you might want to make a map from it before processing the id array, so that the complexing is reduced to O(1) when the delete process begins.
Perhaps This is what you want:
var arr= [{id:1, name: "foo"}, {id:2, name: "bar"}, {id:3, name:"not to be deleted"}];
var idsToDelete = [1, 2];
var res = arr.map((i, idx)=>{
return arr[idx] = idsToDelete.includes(i.id)? undefined : arr[idx]
}).filter(i=>i)
console.log(res)
You can try Lodash.js functions _.forEach() and _.remove()
let valuesArr = [
{id: 1, name: "dog"},
{id: 2, name: "cat"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
{id: 5, name: "pig"},
];
let removeValFromIndex = [
{id: 2, name: "cat"},
{id: 5, name: "pig"},
];
_.forEach(removeValFromIndex, (indi) => {
_.remove(valuesArr, (item) => {
return item.id === indi.id;
});
})
console.log(valuesArr)
/*[
{id: 1, name: "dog"},
{id: 3, name: "rat"},
{id: 4, name: "bat"},
]; */
Don't forget to clone (_.clone(valuesArr) or [...valuesArr]) before mutate your array

Compare and return boolean if two array of objects has the values or not

I have two array of objects which are like,
let A = [{id: "1"}, {id: "2"},{id: "3" }]
let B = [{id: "3"}, {id: "2"}]
Now, I am iterating over A.
return _.map(A) => ({
id: A.id,
isAvaliable: //This needs to be like weather B includes A on the basis of ID , means does B object has this A client ID if yes then set it true or false
})
So, final object which I will get will be,
const result = [{
{id: "1", isavaliable: false},
{id: "2", isavaliable: true},
{id: "3", isavaliable: true},
}
]
So, How do I achieve this ?
Thanks.
First make an array or Set of the B ids, then you can .map A and set isavailable by whether the id is included in the set:
const A = [{id: "1"}, {id: "2"},{id: "3" }];
const B = [{id: "3"}, {id: "2"}];
const haveIds = new Set(B.map(({ id }) => id));
const result = A.map(({ id }) => ({ id, isavailable: haveIds.has(id) }));
console.log(result);
No need to rely on an external library, Array.prototype.map works just fine.
let A = [{ id: "1" }, { id: "2" }, { id: "3" }];
let B = [{ id: "3" }, { id: "2" }];
const merge = (arr1, arr2) =>
arr1.map((a) => ({
id: a.id,
isAvaliable: !!arr2.find((b) => b.id === a.id),
}));
console.log(merge(A, B));
Use lodash 'find' to check id in array B
const A = [{id: '1'}, {id: '2'}, {id: '3' }];
const B = [{id: '3'}, {id: '2'}];
const C = _.map(A, item => {
return {
id: item.id,
isAvailable: _.find(B, {id: item.id}) ? true : false
};
});

How can I remove the name field from a json array?

I have a json array like this:
(3) [{…}, {…}, {…}]
0: {Id: 1, Name: "bask"}
1: {Id: 2, Name: "voll"}
2: {Id: 3, Name: "badminton"}
I want to turn it into something like this:
{1:"bask",2:"voll",3:"badminton"}
You can use reduce to loop through array and build a object of desired key/value pair
let data = [{Id: 1, Name: "bask"},{Id: 2, Name: "voll"},{Id: 3, Name: "badminton"}]
let output = data.reduce((op, {Id, Name}) => {
op[Id] = Name
return op
},{})
console.log(output)
You could take Object.fromEntries with the maped key/value pairs.
var array = [{ Id: 1, Name: "bask" }, { Id: 2, Name: "voll" }, { Id: 3, Name: "badminton" }],
object = Object.fromEntries(array.map(({ Id, Name }) => [Id, Name]));
console.log(object);
You can check out the reduce() function!
let array = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
];
console.log(_.reduce(array, function(result, obj){
result[obj.Id] = obj.Name;
return result;
}, {}));
You can checkout lodash an awesome library with many other such utilities!
You can do this with reduce():
var a = [
{Id: 1, Name: "bask"},
{Id: 2, Name: "voll"},
{Id: 3, Name: "badminton"}
]
b = a.reduce((acc, item) => {
acc[item.Id] = item.Name;
return acc;
}
console.log(b);
You can do it in different ways, here one of them.
let dataArray = [
{id: 1, name: 'bask'},
{id: 2, name: 'voll'},
{id: 3, name: 'badminton'}
]
let ouputObject = {}
dataArray.map(data => {
ouputObject[`${data.id}`] = data.name
})
console.log(ouputObject)
outputObject will be
Object {
1: "bask",
2: "voll",
3: "badminton"
}
Using Array.reduce() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var reduceObj = arr.reduce(function(result, currentElement) {
result[currentElement.Id] = currentElement.Name;
return result;
}, {});
console.log(reduceObj);
Using Array.map() :
var arr = [{
Id: 1,
Name: "bask"
}, {
Id: 2,
Name: "voll"
}, {
Id: 3,
Name: "badminton"
}];
var mapObject = {}
arr.map(obj => {
mapObject[obj.Id] = obj.Name
})
console.log(mapObject);

Is there a lodash function or a 'lodash way' to do a conditional _.map?

So basically, I have an array of objects and I'd like to update only the objects in the array that satisfy a condition. I want to know if there's like a good functional way of solving that problem. Right now I'm using lodash. Here's and example:
var things = [
{id: 1, type: "a", value: "100"},
{id: 2, type: "b", value: "300"},
{id: 3, type: "a", value: "100"}
];
var results = _.map(things, function (thing) {
if(thing.type === "a") {
thing.value = "500";
}
return thing;
});
// => results should be [{id: 1, type: "a", value: "500"}, {id: 2, type: "b", value: "300"}, {id: 3, type: "a", value: "500"}];
There is no need here to use map method.
You can use a simply forEach function by passing a callback function to it.
var results = _.forEach(things, function (thing) {
if(thing.type === "a") {
thing.value = "500";
}
});
You could just map the new objects with a condition inside of Object.assign, without mutating the original object.
var things = [{ id: 1, type: "a", value: "100" }, { id: 2, type: "b", value: "300" }, { id: 3, type: "a", value: "100" }],
results = things.map(o => Object.assign({}, o, o.type === "a" && { value: 500 }));
console.log(results);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Array#map (or Lodash's equivalent) with a ternary that will create a new updated object if the type is a using Object#assign:
var things = [
{id: 1, type: "a", value: "100"},
{id: 2, type: "b", value: "300"},
{id: 3, type: "a", value: "100"}
];
var result = things.map(function (thing) {
return thing.type === 'a' ? Object.assign({}, thing, { value: 500 }) : thing;
});
console.log(result);
This is perhaps a little early, but with the proposal for object rest spread which is currently in stage-3 you could solve it like this:
const things = [
{id: 1, type: "a", value: "100"},
{id: 2, type: "b", value: "300"},
{id: 3, type: "a", value: "100"},
];
const result = things.map(e => e.type === 'a' ? {...e, value: 500 } : e);
console.log(result);

Categories

Resources