简体   繁体   中英

Javascript find object with matching property in array of objects and get another property if exists

I'm looking for an elegant solution to this the following:

In many places of my code, I need to find an object that matches an id in an array of objects and then return a property on that object. The referenced id may or may not exist in the array.

The shortest solution I have come up with is the following:

(wanting to get the title of an item if the item exists, otherwise return none)

arrayofObjects = [ { id: 'a3ff3d', title: 'Tesla', color: 'Red' }, { id: 'r43wesd', title: 'AMC', color: 'Rust }]
wantedObject = { queryTitle: 'Desired Car', id: 'a3ff3d' }


let wantedProperty = arrayOfObjects.some( e => e.id === wantedObject.id) ? arrayOfObjects.find(e => e.id === wantedObject.id).title : 'None Found'

However, this is neither elegant or as efficient as it should be. I'd prefer for it to be a one liner instead of a function.

The smallest method is not necessarily the most efficient. I would do it this way:

let wantedProperty = (arrayOfObjects.find(obj => obj.id === wantedObject.id) || {}).title || 'None Found';

Use Array#find and destructuring.

 const data = [ { id: 'a3ff3d', title: 'Tesla', color: 'Red' }, { id: 'r43wesd', title: 'AMC', color: 'Rust' }]; function search(idToFind){ const res = data.find(({id}) => id === idToFind); return res ? res.title : "Nothing found"; } console.log(search('r43wesd')); console.log(search('fail'));

Actually, you can create a one line, generalized method for your data structure that you can reuse multiple times:

 const arrayOfObjects = [ {id: 'a3ff3d', title: 'Tesla', color: 'Red'}, {id: 'r43wesd', title: 'AMC', color: 'Rust'} ]; const getKey = (a, id, key) => (f = a.find(x => x.id === id)) ? f[[key]] : "Not Found"; console.log(getKey(arrayOfObjects, "a3ff3d", "title")); console.log(getKey(arrayOfObjects, "r43wesd", "color")); console.log(getKey(arrayOfObjects, "someid", "color"));

I thought of 2 possible solution. First the one I do NOT recommend:

array.reduce((acc, cur) => {
    return cur.id == searchedId ? cur.title : acc;
}, "None found");

Especially if you need to use it frequently, avoid "complex" code, even if we are considering one line.

The second option (if you do not really want to use a function) is this one:

Array.prototype.findOrElse = function(cb, objcb, retValue) {
    let findElem = this.find(elem => cb(elem));

    return objcb(findElem) || retValue;
}

You can call it like this:

array.findOrElse(elem => elem.id == searchedId, elem => elem.title, "None found");

Generally I do not choose this way because I prefer not to touch native objects that js provides, but no one forbids it.


EDIT: As @PatrickRoberts made me notice, this is not really an answer. I just found 2 possible solutions that for different reasons I do not recommend. Functions have this advantage: you do not have to repeat the same code, even if it is one line. Think about a possible situation where you may have to retrieve a different property instead of title .

On the other hand, customize a function inside the prototype of Array object is difficult: you try to make that function as generic as possible, with the risk of excessively complicating the function definition.

So why not going with your own defined function?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM