Фильтрация объектов из массива с соответствующим атрибутом из другого массива в порядке другого массива - PullRequest
0 голосов
/ 27 сентября 2018

Я сталкивался с этой проблемой не раз за свою карьеру.Я гуглил и не нашел точного соответствия в этих результатах или в StackOverflow.

Учтите, что у меня есть следующий массив объектов:

let objects = [
    {id: 'doe', descr: 'a deer'},
    {id: 'baz', descr: 'non-sense'},
    {id: 'ray', descr: 'a drop'},
    {id: 'foo', descr: 'effed'},
    {id: 'bar', descr: 'beyond'}
];

Я хотел бы получить только элементы массива, где id соответствует одному из элементов следующего массива, и возвращает их в массиве, который соответствует порядку следующего:

let objectsOrder = ['foo', 'bar', 'baz'];

Я фактически разработал пару решений и представлю одно в видеответьте, используя reduce ниже (я также использовал forEach в других попытках, но не буду это представлять).Я предполагаю, что это также может быть сделано сначала фильтрацией, затем (пользовательской) сортировкой, но это, казалось бы, повторяется дважды.Возможно, другой альтернативой является использование метода (или методов) из lodash, хотя я не уверен, что это будет.

Ответы [ 5 ]

0 голосов
/ 27 сентября 2018

Другим способом было бы получить входные данные в форме, которая подходит для доступа к ключу объекта через lodash _. KeyBy :

let objects = [{id: 'doe', descr: 'a deer'},{id: 'baz', descr: 'non-sense'},{id: 'ray', descr: 'a drop'},{id: 'foo', descr: 'effed'},{id: 'bar', descr: 'beyond'}];
let objectsOrder = ['foo', 'bar', 'baz'];

var keyedObjects = _.keyBy(objects, 'id')
var result = objectsOrder.map(x => keyedObjects[x])

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

Таким образом, вы отображаете на objectsOrder для сохранения порядка и просто используете клавишу для получения доступа в функции карты.

0 голосов
/ 27 сентября 2018

Вы можете взять Map и получить карту объектов в нужном порядке.

var objects = [
        { id: 'doe', descr: 'a deer' }, 
        { id: 'baz', descr: 'non-sense' }, 
        { id: 'ray', descr: 'a drop' }, 
        { id: 'foo', descr: 'effed' }, 
        { id: 'bar', descr: 'beyond' }
    ],
    objectsOrder = ['foo', 'bar', 'baz'],
    result = objectsOrder.map(Map.prototype.get, new Map(objects.map(o => [o.id, o])));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Если некоторые id неизвестны, вы можете добавить фильтр для правдивых предметов.

var objects = [
        { id: 'doe', descr: 'a deer' }, 
        { id: 'baz', descr: 'non-sense' }, 
        { id: 'ray', descr: 'a drop' }, 
        { id: 'foo', descr: 'effed' }, 
        { id: 'bar', descr: 'beyond' }
    ],
    objectsOrder = ['foo', 'bar', 'unknown'],
    result = objectsOrder
        .map(Map.prototype.get, new Map(objects.map(o => [o.id, o])))
        .filter(Boolean);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 27 сентября 2018

Это легко сделать с помощью петли forEach().Не нужно использовать reduce().

let objects = [
    {id: 'doe', descr: 'a deer'},
    {id: 'baz', descr: 'non-sense'},
    {id: 'ray', descr: 'a drop'},
    {id: 'foo', descr: 'effed'},
    {id: 'bar', descr: 'beyond'}
];

let objectsOrder = ['foo', 'bar', 'baz'];
let res = [];
objects.forEach((obj)=>{
  var id = obj.id;
  var idIndex = objectsOrder.indexOf(id);
  if(idIndex !== -1){
    res[idIndex] = obj;
  }
});
console.log(res);
0 голосов
/ 27 сентября 2018

Вам не нужна такая сложная логика.Просто отобразите каждое значение objectsOrder и получите соответствующее значение в массиве objects

let objects = [
    {id: 'doe', descr: 'a deer'},
    {id: 'baz', descr: 'non-sense'},
    {id: 'ray', descr: 'a drop'},
    {id: 'foo', descr: 'effed'},
    {id: 'bar', descr: 'beyond'}
];

let objectsOrder = ['foo', 'bar', 'baz'];

console.log(
  objectsOrder.map(a=>objects.find(b=>b.id==a))
)
0 голосов
/ 27 сентября 2018

Следующий код находится по адресу: https://repl.it/@dexygen/orderFilteredObjects

let objects = [
    {id: 'doe', descr: 'a deer'},
    {id: 'baz', descr: 'non-sense'},
    {id: 'ray', descr: 'a drop'},
    {id: 'foo', descr: 'effed'},
    {id: 'bar', descr: 'beyond'}
];

let objectsOrder = ['foo', 'bar', 'baz'];

let prunedObjects = objects.reduce((pruned, obj) => {
    let orderIndex = objectsOrder.indexOf(obj.id);
    if (orderIndex >= 0) {
      pruned[orderIndex] = obj;
    }
    return pruned;
}, []);

console.log(JSON.stringify(prunedObjects)); //[{"id":"foo","descr":"effed"},{"id":"bar","descr":"beyond"},{"id":"baz","descr":"non-sense"}]
...