通过property的值从对象数组中获取JavaScript对象

Get JavaScript object from array of objects by value of property

本问题已经有最佳答案,请猛点这里访问。

假设我有四个对象的数组:

1
2
3
4
5
6
var jsObjects = [
   {a: 1, b: 2},
   {a: 3, b: 4},
   {a: 5, b: 6},
   {a: 7, b: 8}
];

有没有一种方法可以通过属性b的值来获得第三个对象({a: 5, b: 6},例如没有for...in循环?


Filter对象数组,其属性与值匹配,返回数组:

1
2
3
var result = jsObjects.filter(obj => {
  return obj.b === 6
})

请参见array.prototype.filter()上的MDN文档

1
2
3
4
5
6
7
8
9
10
11
12
const jsObjects = [
  {a: 1, b: 2},
  {a: 3, b: 4},
  {a: 5, b: 6},
  {a: 7, b: 8}
]

let result = jsObjects.filter(obj => {
  return obj.b === 6
})

console.log(result)

Find数组中第一个元素/对象的值,否则返回undefined

1
2
3
var result = jsObjects.find(obj => {
  return obj.b === 6
})

查看array.prototype.find()上的MDN文档

1
2
3
4
5
6
7
8
9
10
11
12
const jsObjects = [
  {a: 1, b: 2},
  {a: 3, b: 4},
  {a: 5, b: 6},
  {a: 7, b: 8}
]

let result = jsObjects.find(obj => {
  return obj.b === 6
})

console.log(result)


1
jsObjects.find(x => x.b === 6)

来自MDN:

The find() method returns a value in the array, if an element in the array satisfies the provided testing function. Otherwise undefined is returned.

旁注:像find()和arrow函数这样的方法不受旧浏览器(比如IE)的支持,所以如果您想支持这些浏览器,应该使用babel来生成代码。


我不知道为什么你反对一个for循环(大概你是指for循环,而不是专门针对..in),他们是快速和容易阅读。不管怎样,这里有一些选择。

for循环:

1
2
3
4
5
6
7
function getByValue(arr, value) {

  for (var i=0, iLen=arr.length; i<iLen; i++) {

    if (arr[i].b == value) return arr[i];
  }
}

滤波器

1
2
3
4
5
6
7
function getByValue2(arr, value) {

  var result  = arr.filter(function(o){return o.b == value;} );

  return result? result[0] : null; // or undefined

}

前额

1
2
3
4
5
6
7
8
9
function getByValue3(arr, value) {

  var result = [];

  arr.forEach(function(o){if (o.b == value) result.push(o);} );

  return result? result[0] : null; // or undefined

}

另一方面,如果您确实是指..in并希望查找任何属性值为6的对象,则必须使用for..in,除非您传递要检查的名称。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
function getByValue4(arr, value) {
  var o;

  for (var i=0, iLen=arr.length; i<iLen; i++) {
    o = arr[i];

    for (var p in o) {
      if (o.hasOwnProperty(p) && o[p] == value) {
        return o;
      }
    }
  }
}


尝试数组过滤法,用property过滤array of objects

1
2
3
4
5
6
var jsObjects = [
   {a: 1, b: 2},
   {a: 3, b: 4},
   {a: 5, b: 6},
   {a: 7, b: 8}
];

使用数组筛选方法:

1
2
3
var filterObj = jsObjects.filter(function(e) {
  return e.b == 6;
});

在循环中使用:

1
2
3
4
5
for (var i in jsObjects) {
  if (jsObjects[i].b == 6) {
    console.log(jsObjects[i]); // {a: 5, b: 6}
  }
}

工作小提琴:https://jsfiddle.net/uq9n9g77/


使用underline.js:

1
var foundObject = _.findWhere(jsObjects, {b: 6});

在ecmascript 6提案中,有Array方法find()findIndex()。MDN还提供了polyfill,您可以在所有浏览器中使用它来获得这些功能。

find()

10

findIndex()

1
2
3
4
5
6
7
8
9
10
function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].findIndex(isPrime) ); // -1, not found
console.log( [4, 6, 7, 12].findIndex(isPrime) ); // 2


好的,有几种方法可以做到这一点,但是让我们从最简单和最新的方法开始,这个函数称为find()

当你用find来表示即使是ie11也不支持它时,也要小心,所以需要注意…

所以你有这个物体,如你所说:

1
2
3
4
5
6
var jsObjects = [
   {a: 1, b: 2},
   {a: 3, b: 4},
   {a: 5, b: 6},
   {a: 7, b: 8}
];

你可以写一个函数,然后这样得到它:

1
2
3
function filterValue(obj, key, value) {
  return obj.find(function(v){ return v[key] === value});
}

使用如下函数:

1
filterValue(jsObjects,"b", 6); //{a: 5, b: 6}

同样,在ES6中,甚至缩短了版本:

1
const filterValue = (obj, key, value)=> obj.find(v => v[key] === value);

此方法只返回与…匹配的第一个值,为获得更好的结果和浏览器支持,可以使用filter

1
const filterValue = (obj, key, value)=> obj.filter(v => v[key] === value);

我们会把[{a: 5, b: 6}]还给你…

此方法将返回一个数组…

您也可以简单地使用for循环,创建如下函数:

1
2
3
4
5
6
7
8
9
function filteredArray(arr, key, value) {
  const newArray = [];
  for(i=0, l=arr.length; i<l; i++) {
    if(arr[i][key] === value) {
      newArray.push(arr[i]);
    }
  }
 return newArray;
}

这样称呼它:

1
filteredArray(jsObjects,"b", 6); //[{a: 5, b: 6}]


如果我理解正确,您想在数组中找到b属性为6的对象吗?

1
2
3
4
5
6
7
var found;
jsObjects.some(function (obj) {
  if (obj.b === 6) {
    found = obj;
    return true;
  }
});

或者如果使用下划线:

1
2
3
var found = _.select(jsObjects, function (obj) {
  return obj.b === 6;
});


如果您要查找单个结果而不是数组,我可以建议减少吗?

这里有一个纯"ole javascript"的解决方案,如果存在匹配的对象,则返回该对象;如果不存在,则返回空值。

1
var result = arr.reduce(function(prev, curr) { return (curr.b === 6) ? curr : prev; }, null);

如何使用lo dash的_.find(collection, [predicate=_.identity], [fromIndex=0])按对象属性值从对象数组中获取对象?你可以这样做:

1
var o = _.find(jsObjects, {'b': 6});

争论:

1
2
3
collection (Array|Object): The collection to inspect.
[predicate=_.identity] (Function): The function invoked per iteration.
[fromIndex=0] (number): The index to search from.

退换商品

1
(*): Returns the matched element (in your case, {a: 5, b: 6}), else undefined.

在性能方面,_.find()更快,因为它只拉第一个属性为{'b': 6}的对象,另一方面,如果您的数组包含多个具有匹配属性集(key:value)的对象,那么您应该考虑使用_.filter()方法。所以在您的例子中,由于您的数组有一个具有此属性的对象,所以我将使用_.find()


您可以将其与箭头函数一起使用,如下所示:

1
2
3
4
5
6
7
8
9
var demoArray = [
   {name: 'apples', quantity: 2},
   {name: 'bananas', quantity: 0},
   {name: 'cherries', quantity: 5}
];

var result = demoArray.filter( obj => obj.name === 'apples')[0];
console.log(result);
// {name: 'apples', quantity: 2}


请参阅本文档https://developer.mozilla.org/en-us/docs/web/javascript/reference/global_objects/object/values例子:

1
2
3
4
5
6
7
8
9
10
11
12
var inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) {
    return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries));
// { name: 'cherries', quantity: 5 }


只需将此答案中最快/最好的部分改进为更可用/更清晰:

1
2
3
4
5
6
7
function getElByPropVal(arr, prop, val){
    for (var i = 0, length = arr.length; i < length; i++) {
        if (arr[i][prop] == val){
            return arr[i];
        }
    }
}

要按特定属性值从对象数组中获取第一个对象,请执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function getObjectFromObjectsArrayByPropertyValue(objectsArray, propertyName, propertyValue) {
  return objectsArray.find(function (objectsArrayElement) {
    return objectsArrayElement[propertyName] == propertyValue;
  });
}

function findObject () {
  var arrayOfObjectsString = document.getElementById("arrayOfObjects").value,
      arrayOfObjects,
      propertyName = document.getElementById("propertyName").value,
      propertyValue = document.getElementById("propertyValue").value,
      preview = document.getElementById("preview"),
      searchingObject;
 
  arrayOfObjects = JSON.parse(arrayOfObjectsString);
 
  console.debug(arrayOfObjects);
 
  if(arrayOfObjects && propertyName && propertyValue) {
    searchingObject = getObjectFromObjectsArrayByPropertyValue(arrayOfObjects, propertyName, propertyValue);
    if(searchingObject) {
      preview.innerHTML = JSON.stringify(searchingObject, false, 2);
    } else {
      preview.innerHTML ="there is no object with property" + propertyName +" =" + propertyValue +" in your array of objects";
    }
  }
}
1
2
3
4
5
6
7
8
9
pre {
  padding: 5px;
  border-radius: 4px;
  background: #f3f2f2;
}

textarea, button {
  width: 100%
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<fieldset>
  <legend>Input Data:</legend>
  <label>Put here your array of objects</label>
  <textarea rows="7" id="arrayOfObjects">
  [
    {"a": 1,"b": 2},
    {"a": 3,"b": 4},
    {"a": 5,"b": 6},
    {"a": 7,"b": 8,"c": 157}
  ]
  </textarea>

 

  <label>property name: </label> <input type="text" id="propertyName"  value="b"/>
  <label>property value: </label> <input type="text" id="propertyValue" value=6 />
     
</fieldset>

<button onclick="findObject()">find object in array!</button>

<fieldset>
  <legend>Searching Result:</legend>
  [cc lang="javascript"]click find

1
2
3
4
5
</P><hr><P>使用find with bind将特定的键值传递给回调函数。</P>[cc lang="javascript"]   function byValue(o) {
       return o.a === this.a && o.b === this.b;
   };  

   var result = jsObjects.find(byValue.bind({ a: 5, b: 6 }));

1
var result = jsObjects.filter(x=> x.b === 6);

会更好,使用返回过滤器有时你不能得到结果(我不知道为什么)


1
var jsObjects = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}, {a: 7, b: 8}];

要访问第三个对象,请使用:jsObjects[2];。要访问第三个对象B值,请使用:jsObjects[2].b;