#javascript
#javascript
Вопрос:
У меня есть следующие два массива объектов
//references
var refs=[
{id:1, name:'John', state:'A'},
{id:2, name:'Obama', state:'P'},
{id:3, name:'Lincoln', state:'P'}
];
//items
var items=[
{ref:refs[0], detailed:true },
{ref:refs[1], detailed:false}
];
Теперь я хочу проверить, содержит ли items ссылки[0] . Как я могу это сделать? Конечно, мы можем сделать
что-то вроде этого
for(item:items){
if(item.ref==refs[0]){
console.log('contains');
break;
}
}
но у меня может быть 2000 ссылок. Есть идеи. Спасибо
Комментарии:
1. Можете ли вы пояснить, почему этот подход не будет работать, если у вас 2000 ссылок?
2. Как наличие большего количества ссылок что-либо меняет, в любом случае вас интересуют только ссылки [0] в соответствии с вашими спецификациями? Я бы не стал проходить через цикл for in, хотя, потому что и элементы, и ссылки являются массивами, поэтому вы можете сделать
while( i<len)
, поскольку элементы[?].ссылки — это ссылка, с которой вы можете сравнить вот так===
3. Нет, это работает. Мне просто кажется, что это пустая трата ресурсов.
4. @JumabekAlihanov — Смотрите мой комментарий к Юхане под моим ответом.
5. Все еще не уверен, каковы требования, если вам нужно просмотреть только один элемент один раз, тогда цикл — это путь, но если у вас много ссылок, и вам нужно знать, есть ли они в элементах, и если да, то каковы значения, тогда вам нужно переопределить элементы. Я обновил свой ответ с возможной оптимизацией.
Ответ №1:
Вы можете использовать Array.filter()
:
console.log(get_ref_item(refs[0], items));
function get_ref_item(ref, items) {
return items.filter(function fi(item){
return ref.id == item.ref.id;
});
}
Комментарии:
1. Обратите внимание, что это практически идентично исходному коду с точки зрения производительности. Просто нет способа избежать перебора всего массива при поиске элементов, если вы уже примерно не знаете, с чего начать поиск.
2. @Juhana — С точки зрения производительности , for с разрывом во многих случаях будет быстрее, в зависимости от того, где в массиве находится искомый элемент. Итак, на самом деле, код OPs лучше в этом отношении. Смотрите: jsperf.com/for-vs-array-filter
3. Обратите внимание, единственная причина, по которой он мог быть эквивалентным (или, может быть, лучше, пришлось бы тестировать), заключается в том, что каждый раз нужно искать во всем массиве, например, если
ref.id
может существовать более одного раза в массиве.
Ответ №2:
Не ясно, в чем здесь проблема, но предполагая, что вы хотели бы знать, есть ли ссылка в элементах, и вам нужно знать это для нескольких ссылок (просматривайте это несколько раз), тогда вам лучше переопределить свои элементы:
//references
var refs=[
{id:1, name:'John', state:'A'},
{id:2, name:'Obama', state:'P'},
{id:3, name:'Lincoln', state:'P'}
];
//items
var items=[
{ref:refs[0], detailed:true },
{ref:refs[1], detailed:false}
];
//if you need to continiously look up a ref in items
// it's better to convert items to an object
// {"refid":{ref:..,detailed:...}}
// assuming every item has a ref and has that ref only once
// and every ref has a unique id
var i = -1,len=items.length,tmp={};
while( i<len){
tmp[items[i].ref.id]=items[i];
}
items=tmp;
console.log("item for refs 0:",items[refs[0].id]);
console.log("item for refs 1:",items[refs[1].id]);
console.log("item for refs 2:",items[refs[2].id]);//undefined, that ref is not it items
Комментарии:
1. Вы можете протестировать свою оптимизацию на основе методов
for
иArray.filter
здесь: jsperf.com/for-vs-array-filter Настройка тестов производительности может быть сложной задачей, поэтому обязательно продумайте это до конца.2. @JaredFarrish Я не использую
for ... in
norArray.filter
илиwhile( i<len)
, потому что он вообще не использует массив. Но я могу сказать вам прямо сейчас, что если бы у вас было более 500 элементов и более 2000 ссылок, делающих элементы объектом с ref.id as keys собирается выполнить любой поиск в массиве, который вы планируете выполнить 200 раз. (если op планировал сопоставить каждый элемент с ссылкой)