Beginner_Hello
Beginner_Hello

Reputation: 367

How to get the last item in an array of objects where the value to a key has a specific character?

With the following array:

arrOfOranges =
[{ "kerp": "thisThing", "time": "@ rocks 3"},
{ "kerp": "otherThing", "green": "blah"},
{ "kerp": "thisThing", "time": "(countriesToTheStart ^"},
{ "kerp": "anotherThing", "yellow": "row row"},
{ "kerp": "anotherThing", "yellow": "rigorous"},
{ "kerp": "thisThing", "time": ",,,,"}]

Each item has the following permanent structure:

[{kerp: ''}] which can be one of 3 values: thisThing, otherThing and anotherThing. And the other key for each object depends on the value of 'kerp'.

If kerp: 'thisThing' then the other key is 'time'. => { "kerp": "thisThing", "time": ""},

If kerp: 'otherThing' then the other key is 'green'. => { "kerp": "otherThing", "green": ""},

If kerp: 'anotherThing' then the other key is 'yellow'. => { "kerp": "anotherThing", "yellow": ""},

I want to get the last item in the array with 'kerp': 'thisThing'. However, the associated value of the 'time' key must contain a letter.

For example in the above array the last item in the array has 'kerp': 'thisThing', however 'time' does not contain a letter.

So I need to get this item from arrOfOranges where it's the last item in the array with kerp: thisThing and time with letters in the value:

{"kerp": "thisThing", "time": "(countriesToTheStart ^"}

Here is what I have so far:

if (arrOfOranges.filter(a=>a.kerp === "thisThing")) {
    // this is just a eay to check if the array contains letters
    if(arrOfOranges.time.match(/[\w]+/g))  {
        return arrOfOranges.slice(-1)[0];
    }
}

However it doesn't work as intended. How would I be able to do this?

Upvotes: 0

Views: 57

Answers (2)

Nick Parsons
Nick Parsons

Reputation: 50684

You can reverse your arrOfOranges using .reverse() and then use .find() on that reversed array. The find method will return the first object that the callback returns true for. Below, I've made it return true for when the time key contains a word-character \w and when the kerp key is equal to "thisThing". Note that I've used .slice() before calling .reverse(), as reverse will modify arrOfOranges in place, which can be prevented by making a copy of the array first:

const arrOfOranges = [{ "kerp": "thisThing", "time": "@ rocks 3"}, { "kerp": "otherThing", "green": "blah"}, { "kerp": "thisThing", "time": "(countriesToTheStart ^"}, { "kerp": "anotherThing", "yellow": "row row"}, { "kerp": "anotherThing", "yellow": "rigorous"}, { "kerp": "thisThing", "time": ",,,,"}];

const search = {kerp: "thisThing", key: "time"};
const res = arrOfOranges.slice().reverse().find(
  obj => obj.kerp === search.kerp && /\w/.test(obj[search.key])
);

console.log(res);

If you need a slightly more efficient approach, you can use a standard for loop to iterate backwards through your array:

const arrOfOranges = [{ "kerp": "thisThing", "time": "@ rocks 3"}, { "kerp": "otherThing", "green": "blah"}, { "kerp": "thisThing", "time": "(countriesToTheStart ^"}, { "kerp": "anotherThing", "yellow": "row row"}, { "kerp": "anotherThing", "yellow": "rigorous"}, { "kerp": "thisThing", "time": ",,,,"}];

const search = {kerp: "thisThing", key: "time"};
function findObj(data, search) {
  for(let i = data.length-1; i >= 0; i--) {
    const curr = data[i];
    if(curr.kerp === search.kerp && /\w/.test(curr[search.key]))
      return curr;
  }
}

console.log(findObj(arrOfOranges, search));

Upvotes: 1

Darshna Rekha
Darshna Rekha

Reputation: 1116

You need to keep the check inside the filter.

const arrOfOranges = [
  { "kerp": "thisThing", "time": "@ rocks 3"},
  { "kerp": "otherThing", "green": "blah"},
  { "kerp": "thisThing", "time": "(countriesToTheStart ^"},
  { "kerp": "anotherThing", "yellow": "row row"},
  { "kerp": "anotherThing", "yellow": "rigorous"},
  { "kerp": "thisThing", "time": ",,,,"}
 ]

const result = arrOfOranges.filter(orange => orange.kerp === "thisThing" && orange.time.match(/[\w]+/g));

console.log(result);

Upvotes: 2

Related Questions