it-roy-ru.com

Получить объект JavaScript из массива объектов по значению свойства

Допустим, у меня есть массив из четырех объектов:

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

Есть ли способ получить третий объект ({a: 5, b: 6}) по значению свойства b, например, без цикла for...in?

560
user765368

Filter массив объектов, свойство которого соответствует значению, возвращает массив:

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

Смотрите Документы MDN на Array.prototype.filter ()

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.

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

Смотрите Документы MDN на Array.prototype.find ()

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)

812
elclanrs
jsObjects.find(x => x.b === 6)

От MDN:

Метод find() возвращает значение в массиве, если элемент в массиве удовлетворяет предоставленной функции тестирования. В противном случае undefined возвращается.


Примечание: такие методы, как find() и функции стрелок, не поддерживаются более старыми браузерами (например, IE), поэтому, если вы хотите поддерживать эти браузеры, вы должны перенести свой код с помощью Babel .

221
Michał Perłakowski

Я не знаю, почему вы против цикла for (вероятно, вы имели в виду цикл for, а не специально для… in), они быстрые и легко читаемые. Во всяком случае, вот несколько вариантов.

Для цикла:

function getByValue(arr, value) {

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

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

.фильтр

function getByValue2(arr, value) {

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

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

}

.для каждого

function getByValue3(arr, value) {

  var result = [];

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

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

}

Если, с другой стороны, вы действительно имели в виду for..in и хотите найти объект с любым свойством со значением 6, то вы должны использовать for..in, если вы не передадите имена для проверки. например.

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;
      }
    }
  }
}
136
RobG

Попробуйте Фильтр массива метод для фильтрации array of objects с помощью property.

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

используя метод фильтра массива:

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

использование для в цикле:

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

Рабочая скрипка:https://jsfiddle.net/uq9n9g77/

31
Rohit Jindal

Используя underscore.js:

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

Похоже, что в предложении ECMAScript 6 есть методы Arrayfind() и findIndex(). MDN также предлагает полифилы, которые вы можете включить, чтобы получить их функциональность во всех браузерах.

find() :

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].find(isPrime) ); // undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

findIndex() :

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
17
Amir

Если я правильно понимаю, вы хотите найти объект в массиве, свойство b которого 6?

var found;
jsObjects.some(function (obj) {
  if (obj.b === 6) {
    found = obj;
    return true;
  }
});

Или, если вы использовали подчеркивание:

var found = _.select(jsObjects, function (obj) {
  return obj.b === 6;
});
14
nickf

ОК, Есть несколько способов сделать это, но давайте начнем с самого простого и самого последнего подхода, чтобы сделать это, эта функция называется find().

Просто будьте осторожны при использовании find, так как даже IE11 не поддерживает его, поэтому его нужно перенести ...

так что у вас есть этот объект, как вы сказали:

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

и вы можете написать функцию и получить ее так:

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

и используйте функцию следующим образом:

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

Также в ES6 для даже укороченной версии:

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

Этот метод возвращает только первое значение, которое соответствует ..., для лучшего результата и поддержки браузера вы можете использовать filter:

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

и мы вернем [{a: 5, b: 6}]...

Этот метод будет возвращать массив вместо ...

Вы также можете просто использовать цикл, создайте такую ​​функцию:

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

и назовите это так:

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

Если вы ищете один результат, а не массив, могу ли я предложить уменьшить? 

Вот решение в виде простого javascript, которое возвращает соответствующий объект, если таковой существует, или ноль, если нет.

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

Как насчет использования _.find(collection, [predicate=_.identity], [fromIndex=0]) of lo-dash для получения объекта из массива объектов по значению свойства объекта. Вы могли бы сделать что-то вроде этого: 

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

Аргументы: 

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

Возвращает

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

С точки зрения производительности, _.find() быстрее, поскольку он извлекает только первый объект со свойством {'b': 6}, с другой стороны, если предполагается, что ваш массив содержит несколько объектов с совпадающим набором свойств (key: value), то вам следует рассмотреть возможность использования метода _.filter(). Так что в вашем случае, поскольку у вашего массива есть один объект с этим свойством, я бы использовал _.find()

9
Simple-Solution

Вы можете использовать его с функцией стрелки, как показано ниже:

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}
6
Shobhit Sharma

См. Эту документацию https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Object/values ​​
Пример : 

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 }
4
asrulsibaoel

Просто улучшил самую быструю/лучшую часть этот ответ чтобы быть более пригодным для повторного использования/понятным:

function getElByPropVal(arr, prop, val){
    for (var i = 0, length = arr.length; i < length; i++) {
        if (arr[i][prop] == val){
            return arr[i];
        }
    }
}
3
Andrew

Чтобы получить первый объект из массива объектов по определенному значению свойства:

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";
    }
  }
}
pre {
  padding: 5px;
  border-radius: 4px;
  background: #f3f2f2;
}

textarea, button {
  width: 100%
}
<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>

  <hr>

  <label>property name: </label> <input type="text" id="propertyName"  value="b"/>
  <label>property value: </label> <input type="text" id="propertyValue" value=6 />
     
</fieldset>
<hr>
<button onclick="findObject()">find object in array!</button>
<hr>
<fieldset>
  <legend>Searching Result:</legend>
  <pre id="preview">click find</pre>
</fieldset>

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

будет лучше, используя return в фильтре, иногда вы не можете получить результат (я не знаю, почему)

0
Died

Использование find с bind для передачи определенных значений ключей в функцию обратного вызова. 

   function byValue(o) { 
       return o.a === this.a && o.b === this.b; 
   };   

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