Как найти значение в многомерном объекте/массиве в Javascript?
У меня есть многомерный объект (это в основном массив):
Object = {
1 : { name : bob , dinner : pizza },
2 : { name : john , dinner : sushi },
3 : { name : larry, dinner : hummus }
}
Я хочу, чтобы иметь возможность искать объект/массив, где ключ является "ужином", и посмотреть, совпадает ли он с "sushi".
Я знаю, что jQuery имеет $.inArray, но он не работает на многомерных массивах. Или, может быть, я ошибаюсь. indexOf также работает только на одном уровне массива.
Нет ли для этого функции или существующего кода?
Ответы
Ответ 1
Если у вас есть массив, такой как
var people = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" }
];
Вы можете использовать метод filter
объекта Array:
people.filter(function (person) { return person.dinner == "sushi" });
// => [{ "name": "john", "dinner": "sushi" }]
В новых реализациях JavaScript вы можете использовать выражение функции:
people.filter(p => p.dinner == "sushi")
// => [{ "name": "john", "dinner": "sushi" }]
Вы можете искать людей, у которых есть "dinner": "sushi"
, используя map
people.map(function (person) {
if (person.dinner == "sushi") {
return person
} else {
return null
}
}); // => [null, { "name": "john", "dinner": "sushi" }, null]
или reduce
people.reduce(function (sushiPeople, person) {
if (person.dinner == "sushi") {
return sushiPeople.concat(person);
} else {
return sushiPeople
}
}, []); // => [{ "name": "john", "dinner": "sushi" }]
Я уверен, что вы можете обобщить это на произвольные ключи и значения!
Ответ 2
jQuery имеет встроенный метод jQuery.grep
, который работает аналогично функции ES5 filter
из @adamse Answer и должен работать нормально в старых браузерах.
Использование примера adamse:
var peoples = [
{ "name": "bob", "dinner": "pizza" },
{ "name": "john", "dinner": "sushi" },
{ "name": "larry", "dinner": "hummus" }
];
вы можете сделать следующее
jQuery.grep(peoples, function (person) { return person.dinner == "sushi" });
// => [{ "name": "john", "dinner": "sushi" }]
Ответ 3
Если вы собираетесь часто выполнять этот поиск, подумайте о том, чтобы изменить формат вашего объекта, так что ужин фактически является ключом. Это похоже на назначение основного кластерного ключа в таблице базы данных. Итак, например:
Obj = { 'pizza' : { 'name' : 'bob' }, 'sushi' : { 'name' : 'john' } }
Теперь вы можете легко получить доступ к нему следующим образом: Object['sushi']['name']
Или, если объект действительно такой простой (просто "имя" в объекте), вы можете просто изменить его на:
Obj = { 'pizza' : 'bob', 'sushi' : 'john' }
И затем войдите в него так: Object['sushi']
.
Очевидно, что это не всегда возможно или в ваших интересах для реструктуризации вашего объекта данных, как это, но дело в том, что лучше всего ответить на вопрос, структурирован ли ваш объект данных наилучшим образом. Создание такого ключа может быть быстрее и создать более чистый код.
Ответ 4
var getKeyByDinner = function(obj, dinner) {
var returnKey = -1;
$.each(obj, function(key, info) {
if (info.dinner == dinner) {
returnKey = key;
return false;
};
});
return returnKey;
}
jsFiddle.
Пока -1
никогда не является допустимым ключом.
Ответ 5
Вы можете найти объект в массиве с помощью Alasql:
var data = [ { name : "bob" , dinner : "pizza" }, { name : "john" , dinner : "sushi" },
{ name : "larry", dinner : "hummus" } ];
var res = alasql('SELECT * FROM ? WHERE dinner="sushi"',[data]);
Попробуйте этот пример в jsFiddle.
Ответ 6
Вы можете использовать простой цикл for:
for (prop in Obj){
if (Obj[prop]['dinner'] === 'sushi'){
// Do stuff with found object. E.g. put it into an array:
arrFoo.push(Obj[prop]);
}
}
Следующий пример скрипта помещает все объекты, содержащие dinner:sushi
в массив:
https://jsfiddle.net/3asvkLn6/1/
Ответ 7
Здесь уже много хороших ответов, поэтому почему бы и нет, используйте библиотеку, такую как lodash или подчеркивание:)
obj = {
1 : { name : 'bob' , dinner : 'pizza' },
2 : { name : 'john' , dinner : 'sushi' },
3 : { name : 'larry', dinner : 'hummus' }
}
_.where(obj, {dinner: 'pizza'})
>> [{"name":"bob","dinner":"pizza"}]
Ответ 8
Мне пришлось искать во вложенной структуре карты сайта первый элемент листа, который обрабатывает заданный путь. Я придумал следующий код, используя только .map()
.filter()
и .reduce
. Возвращает последний найденный элемент, который соответствует пути /c
.
var sitemap = {
nodes: [
{
items: [{ path: "/a" }, { path: "/b" }]
},
{
items: [{ path: "/c" }, { path: "/d" }]
},
{
items: [{ path: "/c" }, { path: "/d" }]
}
]
};
const item = sitemap.nodes
.map(n => n.items.filter(i => i.path === "/c"))
.reduce((last, now) => last.concat(now))
.reduce((last, now) => now);
![Edit 4n4904z07]()
Ответ 9
Я бы постарался не изобретать велосипед. Мы используем object-scan для всех наших потребностей в обработке данных. Это концептуально очень просто, но допускает много интересных вещей. Вот как бы вы решили свой конкретный вопрос
Определение данных
const data = {
1 : { name : 'bob' , dinner : 'pizza' },
2 : { name : 'john' , dinner : 'sushi' },
3 : { name : 'larry', dinner : 'hummus' }
};
Logic
const objectScan = require('object-scan');
const scanner = (input) => {
let obj = null;
objectScan(['*.dinner'], {
filterFn: (key, value, { parents }) => {
if (value === 'sushi') {
obj = parents[0];
}
},
breakFn: () => obj !== null
})(data);
return obj;
};
const result = scanner(data);
Выход
// => result
{
"name": "john",
"dinner": "sushi"
}