Подтвердить что ты не робот

Коллекция коллекции lodash с использованием массива значений

Я хотел бы отфильтровать коллекцию, используя массив значений свойства. Учитывая массив идентификаторов, возвращайте объекты с соответствующими идентификаторами. Есть ли какой-либо метод быстрого доступа с использованием lodash/underscore?

var collections = [{ id: 1, name: 'xyz' },
                   { id: 2,  name: 'ds' },
                   { id: 3,  name: 'rtrt' },
                   { id: 4,  name: 'nhf' },
                   { id: 5,  name: 'qwe' }];
var ids = [1,3,4];

// This works, but any better way?

var filtered = _.select(collections, function(c){    
    return ids.indexOf(c.id) != -1
});
4b9b3361

Ответ 1

Если вы собираетесь использовать этот тип шаблона, вы можете создать mixin, как показано ниже, но он не делает ничего принципиально иного, чем ваш исходный код. Это просто делает его более удобным для разработчиков.

_.mixin({
  'findByValues': function(collection, property, values) {
    return _.filter(collection, function(item) {
      return _.contains(values, item[property]);
    });
  }
});

Затем вы можете использовать его так.

var collections = [
    {id: 1, name: 'xyz'}, 
    {id: 2,  name: 'ds'},
    {id: 3,  name: 'rtrt'},
    {id: 4,  name: 'nhf'},
    {id: 5,  name: 'qwe'}
];

var filtered = _.findByValues(collections, "id", [1,3,4]);

Обновление. Этот ответ старый и неуклюжий. Пожалуйста, используйте ответ от Адама Бодуха для более элегантного решения.

_(collections)
  .keyBy('id') // or .indexBy() if using lodash 3.x
  .at(ids)
  .value();

Ответ 2

Краткое решение lodash, которое использует indexBy() и at().

_(collections)
    .indexBy('id')
    .at(ids)
    .value();

Ответ 3

Мы также можем отфильтровать как

var collections = [{ id: 1, name: 'xyz' },
            { id: 2,  name: 'ds' },
            { id: 3,  name: 'rtrt' },
            { id: 4,  name: 'nhf' },
            { id: 5,  name: 'qwe' }];



        var filtered_ids = _.filter(collections, function(p){
            return _.includes([1,3,4], p.id);
        });

        console.log(filtered_ids);

Ответ 4

Мне нравится ответ jessegavin's, но я расширил его, используя lodash-deep для глубокого сопоставления свойств.

var posts = [{ term: { name: 'A', process: '123A' } }, 
             { term: { name: 'B', process: '123B' } }, 
             { term: { name: 'C', process: '123C' } }];

var result = _.filterByValues(posts, 'term.process', ['123A', '123C']);
// results in objects A and C to be returned

jsFiddle

_.mixin({
    'filterByValues': function(collection, key, values) {
        return _.filter(collection, function(o) {
            return _.contains(values, resolveKey(o, key));
        });
    }
});

function resolveKey(obj, key) {
    return (typeof key == 'function') ? key(obj) : _.deepGet(obj, key);
}

Если вы не доверяете lodash-deep или хотите поддерживать свойства, у которых есть точки в их именах, здесь более защитная и надежная версия:

function resolveKey(obj, key) {
    if (obj == null || key == null) {
        return undefined;
    }
    var resolved = undefined;
    if (typeof key == 'function') {
        resolved = key(obj);
    } else if (typeof key == 'string' ) {
        resolved = obj[key];
        if (resolved == null && key.indexOf(".") != -1) {
            resolved = _.deepGet(obj, key);
        }
    }
    return resolved;
}

Ответ 5

Я заметил, что многие из этих ответов устарели или содержат вспомогательные функции, не перечисленные в документации Lodash. Принятый ответ включает устаревшую функцию _.contains и должен быть обновлен.

Итак, вот мой ответ ES6.

На основе Lodash v4.17.4

_.mixin( {
    filterByValues: ( c, k, v ) => _.filter(
        c, o => _.indexOf( v, o[ k ] ) !== -1
    )
} );

И вызывается как таковой:

_.filterByValues(
    [
        {
            name: 'StackOverflow'
        },
        {
            name: 'ServerFault'
        },
        {
            name: 'AskDifferent'
        }
    ],
    'name',
    [ 'StackOverflow', 'ServerFault' ]
);

// => [ { name: 'StackOverflow' }, { name: 'ServerFault' } ]

Ответ 6

Эти ответы не сработали для меня, потому что я хотел отфильтровать нестандартное значение. Если вы измените keyBy на groupBy, вы можете пройти.

_(collections)
  .groupBy(attribute)
  .pick(possibleValues)
  .values()
  .flatten()
  .value();

Мое первоначальное использование было сбросить вещи, поэтому я отключил pick с помощью omit.

Благодарим Адам Бодух за отправную точку.