Как найти объект в массиве по ключу

The Functional Approach

All the cool kids are doing functional programming (hello React users) these days so I thought I would give the functional solution. In my view it’s actually a lot nicer than the imperatival for and each loops that have been proposed thus far and with ES6 syntax it is quite elegant.

Update

There’s now a great way of doing this called findIndex which takes a function that return true/false based on whether the array element matches (as always, check for browser compatibility though).

var index = peoples.findIndex(function(person) {
  return person.attr1 == "john"
});

With ES6 syntax you get to write this:

var index = peoples.findIndex(p => p.attr1 == "john");

The (Old) Functional Approach

TL;DR

If you’re looking for index where peoples[index].attr1 == "john" use:

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");

Explanation

Step 1

Use .map() to get an array of values given a particular key:

var values = object_array.map(function(o) { return o.your_key; });

The line above takes you from here:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

To here:

var values = [ "bob", "john", "larry" ];

Step 2

Now we just use .indexOf() to find the index of the key we want (which is, of course, also the index of the object we’re looking for):

var index = values.indexOf(your_value);

Solution

We combine all of the above:

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");

Or, if you prefer ES6 syntax:

var index = peoples.map((o) => o.attr1).indexOf("john");

Demo:

var peoples = [
  { "attr1": "bob", "attr2": "pizza" },
  { "attr1": "john", "attr2": "sushi" },
  { "attr1": "larry", "attr2": "hummus" }
];

var index = peoples.map(function(o) { return o.attr1; }).indexOf("john");
console.log("index of 'john': " + index);

var index = peoples.map((o) => o.attr1).indexOf("larry");
console.log("index of 'larry': " + index);

var index = peoples.map(function(o) { return o.attr1; }).indexOf("fred");
console.log("index of 'fred': " + index);

var index = peoples.map((o) => o.attr2).indexOf("pizza");
console.log("index of 'pizza' in 'attr2': " + index);

Есть массив:

let cards = [
	{
		id: 1,
		name: 'card 1',
		img: '',
		des: '<h2>Card 1</h2>' +
				 '<p>Card 1</p>'
	},
	{
		id: 2,
		name: 'card 2',
		img: '',
		des: '<h2>Card 2</h2>' +
				 '<p>Card 2</p>'
	}
]

И функция, для определения случайного числа:

function cardRandom(min, max) {
	return Math.round(Math.random() * (max - min) + min);
};

И элемент, который вызывает функцию нахождения случайного числа и передаёт это число в другую функцию, в виде номера. Каким именно методом перебрать массив объектов, чтобы получить соответствующий объект, под идентификационным номером, соответствующим этому числу?

$('#new-card').on('click', function() {
	let num = cardRandom(1, 51);
	getCard(num);
});

function getCard(num) {

}

Есть filter(), each(), map(), $.grep, find(), цикл for ()
Что лучше использовать? Объектов будет несколько десятков. Поиск рандомный, по ID, с дальнейшим выводом всей информации в объекте.

Для удобства — https://jsfiddle.net/ouodkeLn/365/

You should prefix the id to avoid naming collisions, like this:

var database = 
{
  'row_17' : {id:17, color:'black', width:50},
  'row_34' : {id:34, color:'red',   width:150},
  'row_49' : {id:49, color:'gree',  width:10}
};

At this point you can query the object with this code:

function retrieve(database, id)
{
  id = 'row_' + id;

  if (!database.hasOwnProperty(id))
  {
    return null;
  }

  return database[id];
}

The persist function would be:

function persist(database, obj)
{
  database['row_' + obj['id']] = obj;
}

If you need to keep an order you have first to understand what order you are talking about.

Of the id? Of the insert? Or of an arbitrary property?

There are solutions to all of these by filtering (extracting the items and putting them into a separate array that would be the query result or with additional fields or structures.

EDIT: how to keep insertion order

You’ll need an array that keeps track of order:

database._ordered = [];

On insert, push the item there, too:

database._ordered.push(obj);

Now you can pick single items by key and all items ordered.
There is no way you can have an order in an object, it’s simply the wrong tool for that.

The row_ prefix is recommended to avoid naming collisions with methods and whatnot. An object should hold properties and methods, if you use it like a dictionary at least prevent interference by prefixing.

В этом посте мы обсудим, как определить, содержит ли массив объект с заданным атрибутом в JavaScript.

1. Использование some() метод

Рекомендуемое решение — использовать some() метод, возвращающий true, если в массиве найден хотя бы один объект, удовлетворяющий заданному условию, и false в противном случае.

Следующий пример демонстрирует это, находя человека, живущего в штате NYC.

const people = [

    { name : ‘Jane Smith’, city : ‘New York City’, state : ‘NYC’, zip : ‘10001’ },

    { name : ‘Bob Brown’, city : ‘Colorado’, state : ‘CO’, zip : ‘80011’ },

    { name : ‘Alice Brown’, city : ‘Michigan’, state : ‘MI’, zip : ‘48002’ }

];

const isPresent = people.some(e => e.state === ‘NYC’);

console.log(isPresent);

/*

    результат: true

*/

Скачать  Выполнить код

2. Использование find() метод

Другим решением является использование find() метод, который возвращает первый экземпляр объекта в массиве, который удовлетворяет данному тесту или undefined если он не найден.

const people = [

    { name : ‘Jane Smith’, city : ‘New York City’, state : ‘NYC’, zip : ‘10001’ },

    { name : ‘Bob Brown’, city : ‘Colorado’, state : ‘CO’, zip : ‘80011’ },

    { name : ‘Alice Brown’, city : ‘Michigan’, state : ‘MI’, zip : ‘48002’ }

];

const isPresent = people.find(e => e.state === ‘NYC’) !== undefined;

console.log(isPresent);

/*

    результат: true

*/

Скачать  Выполнить код

3. Использование findIndex() метод

В качестве альтернативы вы можете использовать findIndex() метод, аналогичный методу find() метод, за исключением того, что он возвращает индекс первого экземпляра объекта или -1 если объект не найден.

const people = [

    { name : ‘Jane Smith’, city : ‘New York City’, state : ‘NYC’, zip : ‘10001’ },

    { name : ‘Bob Brown’, city : ‘Colorado’, state : ‘CO’, zip : ‘80011’ },

    { name : ‘Alice Brown’, city : ‘Michigan’, state : ‘MI’, zip : ‘48002’ }

];

const isPresent = people.findIndex(e => e.state === ‘NYC’) !== 1;

console.log(isPresent);

/*

    результат: true

*/

Скачать  Выполнить код

4. Использование filter() метод

Другой вероятный способ — отфильтровать массив, чтобы вернуть все объекты, соответствующие заданному условию. Это можно легко сделать с помощью filter() метод.

const people = [

    { name : ‘Jane Smith’, city : ‘New York City’, state : ‘NYC’, zip : ‘10001’ },

    { name : ‘Bob Brown’, city : ‘Colorado’, state : ‘CO’, zip : ‘80011’ },

    { name : ‘Alice Brown’, city : ‘Michigan’, state : ‘MI’, zip : ‘48002’ }

];

const isPresent = people.filter(e => e.state === ‘NYC’).length > 0;

console.log(isPresent);

/*

    результат: true

*/

Скачать  Выполнить код

5. Использование forEach() метод

Наконец, вы можете выполнить итерацию по массиву, используя forEach() метод и проверьте наличие объекта в массиве.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

const people = [

    { name : ‘Jane Smith’, city : ‘New York City’, state : ‘NYC’, zip : ‘10001’ },

    { name : ‘Bob Brown’, city : ‘Colorado’, state : ‘CO’, zip : ‘80011’ },

    { name : ‘Alice Brown’, city : ‘Michigan’, state : ‘MI’, zip : ‘48002’ }

];

var isPresent = false;

people.forEach(o => {

    if (e => e.state === ‘NYC’) {

        isPresent = true;

    }

});

console.log(isPresent);

/*

    результат: true

*/

Скачать  Выполнить код

Это все о проверке, содержит ли массив объект с заданным атрибутом в JavaScript.

Перевод статьи 4 Methods to Search Through Arrays in JavaScript.

В JavaScript существует несколько довольно эффективных способов поиска элементов в массивах. В самом простом случае вы всегда можете прибегнуть помощи базового цикла for, однако в стандарте ES6 + предусмотрено гораздо большое число методов, предназначенных для циклического перебора элементов массива и поиска среди них тех, что нам нужны.

С таким количеством различных методов поиска и перебора, какой из них рациональнее использовать в каждом из отдельных случаев? Например, в ходе поиска в массиве вы хотите просто узнать, находится ли нужный нам элемент в массиве вообще? А может вам нужен только индекс этого элемента или же он сам?

В отношении каждого отдельного метода, который мы рассмотрим далее, важно понимать, что все они являются встроенными, то есть доступны через свойство прототип Array.prototype. Это означает, что вы можете вызвать их для любого массива, используя точечную нотацию. Это также означает, что все эти методы недоступны для объектов или других типов данных, кроме массивов (хотя частично они могут использоваться для строк).

Далее мы рассмотрим следующие методы массивов Array:

  • Array.includes
  • Array.find
  • Array.indexOf
  • Array.filter

includes

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];

alligator.includes("thick scales"); // вернет true

Метод .include() возвращает логическое значение и идеально подходит для определения факта наличия искомого элемента в массиве. То есть он просто отвечает true или false. Ниже представлен общий вид его синтаксиса:

arr.includes(valueToFind, [fromIndex]);

Как мы можем заметить, этот метод принимает только один обязательный параметр — valueToFind. Это значение затем используется для сопоставления со значениями элементов массива arr. Необязательный параметр fromIndex — это целое число, предписывающее с какого индекса будет начат поиск. По умолчанию это значение равно 0, и поэтому поиск будет осуществляться по всему массиву.

Итак, поскольку в нашем примере выше элемент, с которого начнется поиск имеет индекс 0, то возвращается true. А вот следующая инструкция вернет ложное значение: alligator.include ("thick scales", 1);, так как в этом случае поиск начинается с элемента с индексом 1.

Теперь подробнее рассмотрим несколько важных деталей, на которые стоит обратить внимание. Первое — метод .includes() использует строгое сравнение. Это означает, с учетом уже рассмотренного нами выше примера, что следующая инструкция: alligator.includes('80'); вернет false . Это происходит потому, что хотя вычисление логического выражения 80 == '80' приведет к получению результата true, однако, так как в нашем случае используется строгое сравнение, то 80 === '80' вернет false, то есть значения с разными типами никогда не будут проходить эту проверку.

find

Чем же метод .find() отличается от .include()? Так если бы мы в нашем примере выше изменили название метода «include» на «find», то получили бы следующую ошибку:

Uncaught TypeError: thick scales is not a function

Это произошло потому, что метод .find() требует передачи в качестве параметра функцию. Метод .find() использует не просто оператор сравнения, он передает каждый элемент массива в функцию, передаваемую ему в качестве параметра, и проверяет, возвращает ли она значение true или false.

Таким образом, и хотя следующая инструкция будет работать корректно: alligator.find (() => 'thick scale');, но вы, вероятно, захотите добавить в качестве функции-аргумента свой собственный оператор сравнения для того, чтобы он возвращал что-то нужное нам.

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];

alligator.find(el => el.length < 12); // вернет '4 foot tail'

Эта простая функция, передаваемая нашему методу .find(), проверяет каждый элемент массива, доступный по присваиваемому псевдониму el. Перебор элементов прекращается, когда находится первое совпадение. В нашем случае возвращается true для такого элемента массива, у которого есть свойство length, и его значение менее 12 (напомним, что числа не имеют свойства length). Конечно же, вы можете сделать эту функцию настолько сложной, насколько вам это необходимо, и возвращаемое ей значение соответствовало вашим требованиям.

Заметьте, что результат выполнения нашего кода, из примера выше, не возвращает true, как это было ранее. Это происходит потому, что метод .find() не возвращает логическое значение, а возвращает первый элемент, который соответствует критерию, определенному в функции. Если соответствующего элемента, который соответствует критериям, определенным в вашей функции, то метод вернет undefined. Также обратите внимание, что он возвращает только первый элемент, соответствующий критерию. Таким образом если в массиве более одного элемента, соответствующего критерию в функции, то все равно будет возвращаться только первый, соответствующий критерию в функции. В нашем примере, если бы после элемента со значением 4 foot tail, был другой со значением, в виде строки длиной менее 12 символов, то это ни как не изменило бы наш результат.

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

alligator.find((el, idx) => typeof el === "string" && idx === 2); // вернет '4 foot tall'

И так в нашем массиве три различных элемента, которые удовлетворяют условию (typeof el === 'string'). Если бы это было наше единственное условие, то наш скрипт вернул бы первый элемент массива: thick scales. Но дело в том, что только у одного из элементов нашего массива индекс равен 2 и это элемент со значением 4 foot tall.

Говоря об индексах элементов, схожим методом перебора элементов массива является .findIndex(). Этот метод тоже в качестве параметра принимает функцию, но, как вы уже можете догадаться, он возвращает индекс соответствующего ее критерию элемента, а не его значение.

indexOf

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout"];

alligator.indexOf("rounded snout"); // будет возвращено 3

Как и .include(), метод .indexOf() использует строгое сравнение, а не функцию, как мы это видели рассматривая особенности использования метода .find(). Но, в отличие от метода include(), он возвращает индекс элемента, а не логическое значение. Также вы можете указать, с какого индекса в массиве начинать поиск.

Лично я считаю, что метод .indexOf() может оказаться весьма полезен. Он позволяет легко определить местоположение искомого элемент в массиве, а также проверить присутствует ли в нем элемент с указанным значением. Как же нам понять существует ли указанный элемент в массиве или нет? По сути, мы можем легко определить это, то есть в случае его наличия метод вернет положительное число, и если нет — то -1, что указывает на его отсутствие.

alligator.indexOf("soft and fluffy"); // вернет -1
alligator.indexOf(80); // вернет 1
alligator.indexOf(80, 2); // вернет -1

И, как вы можете видеть, хотя мы могли бы получить методы .find() или .findIndex(), чтобы предоставить нам ту же информацию, писать это намного меньше. Нам не нужно выписывать функцию для сравнения, так как она уже есть в методе .indexOf().

Теперь мы знаем что, метод indexOf() возвращает индекс первого элемента, соответствующего нашему критерию. Тем не менее JavaScript предоставляет нам альтернативный метод поиска элемента в массиве: .lastIndexOf(). Как вы можете догадаться, он делает то же самое, что и метод indexOf(), но начинает поиск с последнего элемента массива в обратном направлении. У этого метода вы также можете указать второй параметр, но помните, что порядок индексов массива остается прежним, не смотря на обратное направление его перебора.

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout", 80];

alligator.indexOf(80); // вернет 1
alligator.lastIndexOf(80); // вернет 4
alligator.indexOf(80, 2); // вернет 4
alligator.lastIndexOf(80, 4); // вернет 4
alligator.lastIndexOf(80, 3); // вернет 1

filter

const alligator = ["thick scales", 80, "4 foot tail", "rounded snout", 80];

alligator.filter(el => el === 80); //вернет [80, 80]

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

Говоря о методе .filter() важно понимать, что он возвращает все элементы, соответствующие вашему критерию, то есть все элементы, которые вы хотите “отфильтровать”.

Заключение

В самом простом случае, когда мне необходимо найти в массиве какое-либо значение я использую метод .find(), но, как вы могли заметить, применение какого-либо метода зависит от конкретного случая.

Вам нужно только узнать существует ли в массиве элемент с определенным значением? Используйте метод .includes().

Вам нужно получить сам элемент массива, значение которого соответствует определенному критерию? Используйте методы .find() или .filter() для получения элементов.

Вам нужно найти индекс какого-либо элемента? Используйте методы .indexOf() или .findIndex() для использования более сложного критерия поиска.

Массивы в примерах, которые мы здесь рассмотрели на самом деле простые. Однако на практике вы можете столкнуться с более сложными случаями, например, с массивами объектов. Вот несколько простых примеров практик, которые вам могут пригодится, для работы с массивами, состоящими из вложенных объектов:

const jungle = [
  { name: "frog", threat: 0 },
  { name: "monkey", threat: 5 },
  { name: "gorilla", threat: 8 },
  { name: "lion", threat: 10 }
];

// разберем объект, перед использованием методов поиска .include () или .indexOf ()
const names = jungle.map(el => el.name); // веренет ['frog', 'monkey', 'gorilla', 'lion']
console.log(names.includes("gorilla")); // веренет true
console.log(names.indexOf("lion")); // веренет 3 - что будет соответствовать верному положению элемента, при условии, что сортировка нового массива names не проводилась


// methods we can do on the array of objects
console.log(jungle.find(el => el.threat == 5)); // веренет объект - {name: "monkey", threat: 5}
console.log(jungle.filter(el => el.threat > 5)); // вернет массив - [{name: "gorilla", threat: 8}, {name: 'lion', threat: 10}]

В общем, это отличный пример для ознакомления с методами поиска в массивах. Изучив их, возможно скоро вы сможете стать настоящими профессионалами эффективного использования массивов JavaScript!

Понравилась статья? Поделить с друзьями:
  • Как найти щенка который убежал
  • Как найти номер осаго по vin
  • Как составить договор семейный кодекс
  • Как найти файл чтобы удалить другой
  • Как правильно составить расчет процентов