Jean Pierre
Jean Pierre

Reputation: 321

Use the resulted object by find() to ternary operation

There is an array of objects of this form:

const rows = [{name: "john", color: "blue", height: 177, weight: 82},
              {name: "anna", color: "red", height: 167, weight: 62},
              {name: "mike", color: "green", height: 181, weight: 78},
              {name: "sue", color: "red", height: 164, weight: 57}];

I need to find the first element that satisfies a condition and use it in the ternary, something like:

{rows.find(a => a.color === "red" && a.name === "anna") ? ... : ... } 

Is there a way to get the result from the condition into the middle ternary term? Like:

{rows.find(a => a.color === "red" && a.name === "anna") ? a.height * a.width : null } 

Upvotes: 0

Views: 655

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074989

There's no one-liner for your example with color, width, and height. (Actually, there is,¹ but...) You need to either search again (which will often be just fine, but...) or store the search result in a variable so you can use it twice.

It looks like you're using this in a JSX expression. Typically grab the things you can to locals prior to the expression, then use those locals:

const entry = rows.find(a => a.color === "red" && a.name === "anna");
const result = entry ? a.height * a.width : null;
// ...later in your JSX...
{result} 

Another option if it's a common operation is to (as always) put it in a reusable function:

// Somewhere it can be reused:
function areaOfOptionalObject(obj) {
    return obj ? obj.width * obj.height : null;
}
// In your JSX:
{areaOfOptionalObject(rows.find(a => a.color === "red" && a.name === "anna"))}

Where you draw the line is a judgement call. For instance, you might put the find in the function:

// Somewhere it can be reused:
function areaOfMatchingObject(array, predicate) {
    const obj = array.find(predicate);
    return obj ? obj.width * obj.height : null;
}
// In your JSX:
{areaOfMatchingObject(rows, a => a.color === "red" && a.name === "anna")}

¹ The one-liner is:

{rows.filter(a => a.color === "red" && a.name === "anna").map(a => a.weight * a.height)[0] ?? null}

...but it fully traverses rows (rather than stopping when it finds something), creates two unnecessary temporary arrays, and is a bit...awkward. Still, it works, and rows probably isn't all that big and the temporary arrays aren't really a big deal.

Thanks @VLAZ for pointing out that filter -> map [0] would do it!

Upvotes: 3

dellink
dellink

Reputation: 564

You can do this in this way:

const found = rows.find(a => a.color === "red" && a.name === "anna");
const res = found ? found.height * found.width : null;

Upvotes: 2

Related Questions