How to map an object by given key using lodash? - javascript

I have an object that looks something like this
{id: "2", name: "foo", price: "1"}
I want to transform this to the following
{2: {id: "2", name: "foo", price: "1"}}
I'm able to achieve this today if I wrap this object with a simple array like so thanks to the friendly keyBy method for array
_.keyBy([action.response], function(item) { return item.id; });
What I would prefer of course is the same result but without having to wrap this with an array first. Does transform/reduce or some other lodash v4 method provide this functionality?

Short solution based on ES6 computed property names: { [obj.id]: obj }
Example:
var obj = {id: "2", name: "foo", price: "1"}
var transformed = { [obj.id]: obj }
console.log(transformed)

You can do this directly with a function:
function convert(obj) {
var result = {}
result[obj.id] = obj
return result
}
Is that what you are looking for?

Related

How to remove object key value of an object array?

I have an object array with object key value.
arr = [obj1:{name:"Jack", surname:"Peralto"}, obj2:{name:"Husnu", surname:"White"}]
I do not want to see obj1 and obj2 labels. Because of these labels I could not use a word template package.
So I want to convert it to this form.
arr = [{name:"Jack", surname:"Peralto"}, {name:"Husnu", surname:"White"}]
.map function does not work at first array.
arr.map(o=>o)
Why I have an array like this? I should use reduce function and obj1 and obj2 labels are key value when I create object array. Now I don't need them.
When you fix the syntax errors in your code ([obj1:{... is not a valid data structure) you can use Object.values to get at the nested objects.
const obj = {
obj1: {
name: "Jack",
surname: "Peralto"
},
obj2: {
name: "Husnu",
surname: "White"
}
};
console.log(Object.values(obj));
its not the right syntax of array you have used array don't have key value pair
use this syntax if you are using object of objects with key value pair
const obj = {
obj1: {
name: "Jack",
surname: "Peralto"
},
obj2: {
name: "Husnu",
surname: "White"
}
};
or use this an array contains object
arr = [
{name:"Jack", surname:"Peralto"},
{name:"Husnu", surname:"White"}
]

Using the spread operator on an array with objects

I got a Javascript object which looks like this:
{
key1: {
itemId: "someId",
myValue: "value"
},
key2: {
itemId: "someId2",
myValue: "value2"
}
}
I also got an array to which I push items like this:
myArr.push({[item.itemId] : anotherDefinedObject}); //inside a loop on items
I then want to join all the items I pushed to the array to the first object. Meaning that if for example the items ids were "key3" and "key4" I would get this object:
{
key1: {
itemId: "someId",
myValue: "value"
},
key2: {
itemId: "someId2",
myValue: "value2"
},
key3: { //the object that was added },
key4: { //the object that was added }
}
I tried doing it with the spread operator:
return {...object, ...myArr}
But then instead of getting what I needed, I get "0", "1" and such as the keys in the new object (since 0,1 etc are the keys of the arrays).
How do I concatenate the object and the array the way I want?
rather my myArray create myObject.
myObject = {}
myObject[item.itemId] = anotherDefinedObject;
Then
return {...object, ...myObject}
const obj = {key1: 1};
const myArr = [{key2: 2}];
myArr.forEach(val => Object.assign(obj, val));
console.log(obj); // {key1: 1, key2: 2}
What you're looking to achieve here is not possible with the spread operator; it's working exactly as intended and the functionality cannot be changed as JS doesn't allow operator overloading. Your best bet is to loop through myArr and add each item in the array to the object using your own code.
P.S. As the comments suggest, in the future you should really provide more examples of your input, the current output, and your intended output; it was quite difficult to follow without it.

acessing new object from Object.keys and forEach method javascript

I'm trying to create a new object (newobj) with new keys and props from a poorly structured existing array of object (arrays?) ex.
[{"product":["1009", "name", "price", "image", "description"]},
{"product":["1004", "name2", "price2", "image2", "description2"]}]
I'm getting result I want but newobj does not update outside of the scope of the forEach method (more than 1 result). My question is what am I not getting ? Is forEach incorrect method with this type obj?
var newobj = {};
Object.keys(oldobj).forEach(function(prop) {
newobj["id"] = Number(oldobj[prop]["product"][0]),
newobj["name"] = oldobj[prop]["product"][1],
newobj["price"] = Number(oldobj[prop]["product"][3]),
newobj["image"] = "url" + oldobj[prop]["product"][0] + ".jpg",
newobj["description"] = oldobj[prop]["product"][2];
// this works
// console.log(JSON.stringify(newobj));
});
// this only updated with one
app.locals.newobj = newobj;
I've also tried mapping (w/ underscore) but I have the same result, I can't access outside scope.
_.each(mappedobj, function(prop) {
_.each(prop["product"][0], function(vals){
newobj["id"] = Number(prop["product"][0]);
console.log(JSON.stringify(newobj));
});
});
If you want all the values from the old object, you need to make newobj an array of objects. You can use .map() to do this transformation.
Object and array destructuring is a convenient way to avoid all those hard-coded indexes. And by naming the parameter variables properly, you can use object literal shorthand to create the resulting objects more easily.
var oldobj = [{
"product": ["1009", "name", "price", "image", "description"]
},
{
"product": ["1004", "name2", "price2", "image2", "description2"]
}
];
var newobj = oldobj.map(({product: [id, name, price, url, description]}) =>
({id: Number(id), name, price: Number(price), url: `url${url}.jpg`, description})
);
console.log(newobj);
Try this
let newObject = _.map(oldObject, (item) => {
return {
id: item.product[0],
name: item.product[1],
price: item.product[2],
image: item.product[3],
description: item.product[4]
};
});
If you want to convert an array of poorly structured object to an array of well structured ones, you can use Array.prototype.map from VanillaJS:
const data = [
{"product": ["1009", "name", "120", "image", "description"]},
{"product": ["1004", "name2", "250", "image2", "description2"]},
{"product": ["1012", "name3", "85", "image3", "description3"]}
];
const products = data.map(({ product }) => {
const [id, name, price, image, description] = product;
return {
id: Number(id),
name,
price: Number(price),
image: `url${image}.jpg`,
description
};
});
console.log(products);

Loop through an array of objects and get where object.field equals value

I'm currently working on a small application where I have to loop through an enormous array of objects. What would be the most efficient method to perform this?
var array = [
{
id: "1",
name: "Alpha"
},
{
id: "2",
name: "Beta"
},
...
];
I'd like to get each object where name equals "Alpha". I'm currently using a simple if statement to filter the objects with a different name value out, but I wonder if there's a more efficient way to do this, performance-wise.
It's worth to mention that I'll push the matching results into a new array.
No, there is no more efficient way.
The alternative is to build and maintain some kind of internal data structure which allows you to find the desired elements faster. As usual, the trade off is between the work involved in maintaining such a structure vs the time it saves you.
I don't have any way about which I would know it's more effective.
But if you had your objects ordered by name you could stop your search imideatly upon reaching an object whose name is not equal to "Alpha".
To find the first object you're looking for you can use binary search and from this Object you go up and down until at both ends you reach an object which isn't named "Alpha" or the end of array.
This is only a way of optimizing and will require time to sort the array and also will take more time when adding an element.
There's a JavaScript function exactly for this kind of task. Filter
From the Docs
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Here is a small example by code for getting all element from array which has a certain 'name' field:
const arr = [
{name: 'Abc'},
{name: 'Xyz'},
{name: 'Lmn'},
{name: 'Xyz'},
{name: 'Xyz'}
];
let response = findByName('Xyz');
console.log(response);
function findByName (name) {
return arr.filter((element) => {
return element.name = name;
});
}
If you need more than one time a collection with a given name, you could use an object with the names as hashes and have instantly access to the items.
var array = [{ id: "1", name: "Alpha" }, { id: "2", name: "Beta" }, { id: "3", name: "Beta" }, { id: "4", name: "Gamma" }, { id: "5", name: "Beta" }, { id: "2", name: "Alpha" }],
hash = Object.create(null);
array.forEach(function (a) {
if (!hash[a.name]) {
hash[a.name] = [];
}
hash[a.name].push(a);
});
console.log(hash);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Given an array of objects, find the object with a particular key

Given an array of objects, what is the best way to find the object with a particular key in JS?
Using jQuery and underscoreJS is fine. I'm just looking for the easiest / least code answer.
Example:
An array of objects, where each object has a "name". Find the object with a particular "name".
var people = [{name: "A"}, {name: "B"}, {name: "C"}];
My current solution:
Pass in the array, the key (e.g. "name"), and the value (e.g. "C").
function getObject(myArray, searchKey, searchValue) {
myArray.forEach(function(element){
if (element[searchKey] == searchValue) {
return element;
}
});
}
You can use Underscore.js's _.where function, like this
console.log(_.where(people, {
"name": "C"
}));
# [ { name: 'C' } ]
This returns all the objects in the array, which exactly matches the object we pass as the second argument.
You should go with grep of jQuery
var people = [{name: "A"}, {name: "B"}, {name: "C"}];
var obj1= jQuery.grep(people,function(n,i){return (n.name=='A')})
Using _.filter:
var people = [{name: "A"}, {name: "B"}, {name: "C"}];
var filteredPeople = _.filter(people, function(obj){
return obj['name'] == 'C';
});
console.log(JSON.stringify(filteredPeople)) // [{"name":"C"}]
If you want an array without the matched object(s), use _.reject:
var filteredPeople = _.reject(people, function(obj){
return obj['name'] == 'C';
});
console.log(JSON.stringify(filteredPeople)) // [{name: "A"}, {name: "B"}]
Without any custom library you can also do this. Please take a look at the following code
var people = [{name: "A"}, {name: "B"}, {name: "C"}],
match=function(element){
return element.name==="A";
};
console.log(people.filter(match));
But it is kind of static code . I don't know how to pass the key and value to the match() function.
I'm surprised not to find the obvious answer here, so: To do that with Underscore, you'd use _.find:
function getObject(myArray, searchKey, searchValue) {
return _.find(myArray, function(entry) { return entry[seachKey] === searchValue; });
}
You don't need Underscore for this, though; JavaScript's array type has find (as of ES5):
function getObject(myArray, searchKey, searchValue) {
return myArray.find(function(entry) { return entry[searchKey] === searchValue; });
}
As of ES2015+, you can make it more concise with an arrow function and destructuring:
function getObject(myArray, searchKey, searchValue) {
return myArray.find(({[searchKey]: value}) => value === searchValue);
}
Live example of that last one:
function getObject(myArray, searchKey, searchValue) {
return myArray.find(({[searchKey]: value}) => value === searchValue);
}
const people = [{name: "A"}, {name: "B"}, {name: "C"}];
console.log(getObject(people, "name", "C"));

Categories