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

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

给定一个对象数组,我正在尝试编写一个方法来获取项目的索引,其中特定 属性 具有在数组中出现 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

我更喜欢格式正确的 underscore/lodash 解决方案,而不是 20 多行的纯 JS 解决方案。如果您可以使用纯 JS 以 less 的方式完成,那很好。

我已经用 _.groupBy 和 _.pluck 尝试了一些东西来取出单独的列表,但找不到将该信息转换回原始数组的索引的方法。

我不确定你从哪里得到 20 多行 js,但你需要最简单的 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);

另一种变体,具有 mapfilter 功能

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);

下面的 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;
}

如果 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

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

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

第一步是使用filter() to get the objects that have the correct owner. Then, it's just a matter of using nthItem to find the object in the filtered result. If it exists, we use indexOf()到returnfoods中第n项的索引。 Returns -1 如果没有项目存在。