Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the array index for an item based on one of its properties

Given an array of objects, I'm trying to write a method that can get the index of a item where a specific property has a value that has occurred n times in the array.

What I'm trying to achieve is probably easier described by this code:

var foods = [
    {
        name: "orange",
        owner: "bob"
    },
    {
        name: "carrot",
        owner: "fred"
    },
    {
        name: "apple",
        owner: "bob"
    },
    {
        name: "onion",
        owner: "fred"
    },
    {
        name: "banana",
        owner: "bob"
    },
    {
        name: "pear",
        owner: "bob"
    }
];

function getIndex(owner, nthItem){
    // solution code
}

getIndex("bob", 3); // should return 4 as it is the index of bob's 3rd item in foods

I'd prefer a well-formed underscore/lodash solution as opposed to a 20+ line-long pure JS one. If you can do it in less with pure JS then that's fine ofc.

I've tried some stuff with _.groupBy and _.pluck to get the individual lists out, but can't find a way to translate that information back into an index from the original array.

like image 688
Jazcash Avatar asked Jan 07 '23 04:01

Jazcash


2 Answers

I not sure where you get 20+ lines in js, but you need simplest for loop:

var foods = [
    {
        name: "orange",
        owner: "bob"
    },
    {
        name: "carrot",
        owner: "fred"
    },
    {
        name: "apple",
        owner: "bob"
    },
    {
        name: "onion",
        owner: "fred"
    },
    {
        name: "banana",
        owner: "bob"
    },
    {
        name: "pear",
        owner: "bob"
    }
];

function getIndex(owner, nthItem) {
  var cur = 0;
  for (var i = 0; i < foods.length; i++) {
    if (foods[i].owner == owner) {
      if (cur + 1 == nthItem) return i;
      cur += 1;
    }
  }
  return -1;
}

document.body.innerHTML = getIndex("bob", 3);

Yet another variant, with map and filter functions

var foods = [{
  name: "orange",
  owner: "bob"
}, {
  name: "carrot",
  owner: "fred"
}, {
  name: "apple",
  owner: "bob"
}, {
  name: "onion",
  owner: "fred"
}, {
  name: "banana",
  owner: "bob"
}, {
  name: "pear",
  owner: "bob"
}];

function getIndex(owner, nthItem) {
  var item = foods.map(function(el, index) {
      return {
        el: el,
        index: index
      };
    })
    .filter(function(el) {
      return el.el.owner == owner;
    })[nthItem-1];
  
  return item? item.index : -1;
}

document.body.innerHTML = getIndex("bob", 3);
like image 58
Grundy Avatar answered Jan 09 '23 20:01

Grundy


If the foods array does not change, a simpler solution may be to create a hashmap from owner to array index and do a hashmap lookup.

var foods = [
    {
        name: "orange",
        owner: "bob"
    },
    {
        name: "carrot",
        owner: "fred"
    },
    {
        name: "apple",
        owner: "bob"
    },
    {
        name: "onion",
        owner: "fred"
    },
    {
        name: "banana",
        owner: "bob"
    },
    {
        name: "pear",
        owner: "bob"
    }
];

var hashmap = foods.reduce(
    function (prev, curr, i, arr) {
        if (curr.owner in prev)
            prev[curr.owner].push(i);
        else
            prev[curr.owner] = [i];
        return prev;
    }, {}); // hashmap contains { bob: [ 0, 2, 4, 5 ], fred: [ 1, 3 ] }

function getIndex(owner, nthItem){
    return hashmap[owner][nthItem - 1];
}

getIndex("bob", 3); // returns 4
like image 24
Adeel Zafar Soomro Avatar answered Jan 09 '23 20:01

Adeel Zafar Soomro