2015-09-03 2 views
4

У меня есть объект массива:Javascript массив фильтр данных из другого

[ 
    { id:1, name: 'Pedro'}, 
    { id:2, name: 'Miko'}, 
    { id:3, name: 'Bear'}, 
    { id:4, name: 'Teddy'}, 
    { id:5, name: 'Mouse'} 
] 

и имеют массив с идентификаторами [1,3,5]

Как отфильтровать массив объектов, чтобы оставить записи только с идентификаторами от второго? Спасибо!

+0

Большой вопрос, также в ответах, какой заказ вы предпочитаете, исходный порядок данных или порядок заданного идентификатора для фильтрации? –

+0

Мне нужно следующее: [ {id: 1, имя: 'Pedro'}, {id: 3, имя: 'Bear'}, {id: 5, имя: 'Mouse'} ] –

ответ

7

Попробуйте это (fiddle):

var array = [ 
    { id:1, name: 'Pedro'}, 
    { id:2, name: 'Miko'}, 
    { id:3, name: 'Bear'}, 
    { id:4, name: 'Teddy'}, 
    { id:5, name: 'Mouse'} 
]; 

var filterArray = [1,3,5]; 

var filtered = array.filter(function(item) { 
    return filterArray.indexOf(item.id) !== -1; 
}); 
+0

You = == gentlePerson && ученый –

0

Вы можете использовать цикл на массиве объектов и проверить hasOwnProperty в другом цикл для каждых идентификаторов в [1,3,5] (выйти из цикла как только идентификатор найден) , (И вырваться из более крупного for-цикла, когда будут найдены все идентификаторы). Если ваш объект массива упорядочен (например, элементы отсортированы с наименьшего id на самый большой идентификатор), а также ваш список, это решение должно быть достаточно эффективным.

var c = 0; 
for(var i =0; i< objects.length; i++){ 
    for(var v =0; v< list.length; v++) 
    if(objects[i].hasOwnProperty(list[v])){ 
     delete objects[i]; c++; break; 
    } 
    if(c===list.length) break; 
} 

или используйте array.splice(i, 1);, если вы не хотите пустого слота.

-1

Использование filter и indexOf будет делать трюк:

var filteredArray = dataArray.filter(function(obj) { 
    return idsArray.indexOf(obj.id) > -1; 
}); 

Однако indexOf имеет линейную работу, и она будет называться много раз.

В ES6 вы можете использовать набор вместо которого has вызова имеет сублинейную производительность (в среднем):

var idsSet = new Set(idsArray), 
    filteredArray = dataArray.filter(obj => idsSet.has(obj.id)); 

Предполагая toString метод ваших идентификаторов инъективен, вы можете добиться чего-то подобного в ES5:

var idsHash = Object.create(null); 
idsArray.forEach(function(id) { 
    idsHash[id] = true; 
}); 
var filteredArray = dataArray.filter(function(obj) { 
    return idsHash[obj.id]; 
}); 
+0

Это работает только в среде, поддерживающей ES2015. – nils

+0

Почему downvote? – Oriol

0

Вы можете использовать filter method в массиве:

var data = [ 
    { id:1, name: 'Pedro'}, 
    { id:2, name: 'Miko'}, 
    { id:3, name: 'Bear'}, 
    { id:4, name: 'Teddy'}, 
    { id:5, name: 'Mouse'} 
]; 

var ids = [1, 3, 5]; 

var filteredData = filterData(data, 'id', ids[1]); 

function filterData(data, prop, values) { 
    return data.filter(function(item) { 
     return ~values.indexOf(item[prop]); // ~ returns 0 if indexOf returns -1 
    }); 
} 

См. Его в действии in this JSFiddle.

0

Или, если вы используете JQuery, другой вариант может быть:

var arr1 = [1, 3, 5], 
    arr2 = [{ id: 1, name: 'Pedro' }, 
    { id: 2, name: 'Miko' }, 
    { id: 3, name: 'Bear' }, 
    { id: 4, name: 'Teddy' }, 
    { id: 5, name: 'Mouse' }], 
    filtered = $.grep(arr2, function (item) { 
    if (arr1.indexOf(item.id) > -1) { 
     return true; 
    } 
}); 
2

Может принимать Array.prototype.reduce в сочетании с Array.prototype.some. Это сохраняет порядок заданного массива need.

var data = [ 
 
     { id: 3, name: 'Bear' }, 
 
     { id: 4, name: 'Teddy' }, 
 
     { id: 5, name: 'Mouse' }, 
 
     { id: 1, name: 'Pedro' }, 
 
     { id: 2, name: 'Miko' }, 
 
    ], 
 
    need = [1, 3, 5], 
 
    filtered = need.reduce(function (r, a) { 
 
     data.some(function (el) { 
 
      return a === el.id && r.push(el); 
 
     }); 
 
     return r; 
 
    }, []); 
 

 
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');

Чтобы сохранить порядок data вы можете использовать Array.prototype.filter:

var data = [ 
 
     { id: 3, name: 'Bear' }, 
 
     { id: 4, name: 'Teddy' }, 
 
     { id: 5, name: 'Mouse' }, 
 
     { id: 1, name: 'Pedro' }, 
 
     { id: 2, name: 'Miko' }, 
 
    ], 
 
    need = [1, 3, 5], 
 
    filtered = data.filter(function (a) { 
 
     return ~need.indexOf(a.id); 
 
    }); 
 

 
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');

1

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

Однако эти решения являются O (n^2), поэтому, учитывая набор данных, достаточно большой, отставание может стать заметным. В этом случае вы должны создать индекс перед выбором элементов.

Пример:

function filterFast(data, ids) { 
    var index = ids.reduce(function(a,b) {a[b] = 1; return a;}, {}); 
    return data.filter(function(item) { 
     return index[item.id] === 1; 
    }); 
} 

И некоторые бенчмаркинг может быть протестирована here.

Смежные вопросы