基于项的某个属性获取该项的数组索引

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

本文关键字:数组 获取 索引 属性 于项      更新时间:2023-09-26

给定一个对象数组,我正在尝试编写一个方法,该方法可以获取某个项的索引,其中某个特定属性的值在数组中出现了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和_.pull来获取单个列表,但找不到将这些信息从原始数组转换回索引的方法。

我不确定在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);

还有一种变体,具有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);

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

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

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

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

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

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