根据项目的某个属性获取项目的数组索引

时间:2015-11-15 15:07:57

标签: javascript arrays underscore.js lodash

给定一个对象数组,我试图编写一个方法来获取项目的索引,其中某个特定属性的值在数组中发生n次。

此代码可能更容易描述我想要实现的目标:

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

我更喜欢一个结构良好的下划线/ lodash解决方案,而不是一个20+线长的纯JS解决方案。如果你能用纯粹的JS做到这一点,那么那就好了。

我已尝试使用_.groupBy和_.pluck来获取单个列表,但无法找到将该信息转换回原始数组索引的方法。

4 个答案:

答案 0 :(得分:4)

我不确定你在js中获得20多行,但你需要最简单的for循环:



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);
&#13;
&#13;
&#13;

另一种变体,mapfilter函数

&#13;
&#13;
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);
&#13;
&#13;
&#13;

答案 1 :(得分:2)

低于getIndex函数应解决您的问题,如果它没有找到getIndex函数的预期输出,则会返回-1

function getIndex(owner, nthItem){
  var noOfTimes = 1;
  for(var i = 0; i < foods.length && noOfTimes <= nthItem; i++) {
    if(foods[i].owner == owner) noOfTimes++;
  }
  //returns -1 if it did not find the expected output.
  return i >= foods.length || noOfTimes < nthItem  ?  -1 : i - 1;
}

答案 2 :(得分:2)

如果foods数组没有改变,更简单的解决方案可能是从所有者到数组索引创建一个hashmap并进行hashmap查找。

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

答案 3 :(得分:1)

这是一个简单的lodash解决方案:

function getIndex(owner, nthItem) {
    return _.indexOf(foods,
        _.filter(foods, { owner: owner })[nthItem - 1]);
}

第一步是使用filter()来获取具有正确owner的对象。然后,只需使用nthItem在过滤结果中查找对象即可。如果存在,我们使用indexOf()返回foods中第n项的索引。如果没有项目,则返回-1