Сортировка уникального массива по идентификатору и сохранение последнего значения

#javascript #arrays #typescript #sorting

#javascript #массивы #typescript #сортировка

Вопрос:

У меня есть следующее

 let arr = [
  { id: 1, referenceId: 1, type: "normal", name: "a" },
  { id: 2, referenceId: 1, type: "normal", name: "b" },
  { id: 3, referenceId: 3, type: "chat", name: "c" },
  { id: 4, referenceId: 4, type: "normal", name: "d" },
  { id: 5, referenceId: 5, type: "chat", name: "e" },
  { id: 6, referenceId: 3, type: "chat", name: "f" }
];
 

Я хочу, чтобы вывод выглядел следующим образом :

 [
  { id: 1, referenceId: 1, type: "normal", name: "a" },
  { id: 2, referenceId: 1, type: "normal", name: "b" },
  { id: 4, referenceId: 4, type: "normal", name: "d" },
  { id: 5, referenceId: 5, type: "chat", name: "e" },
  { id: 6, referenceId: 3, type: "chat", name: "f" }
];
 

Я хочу отсортировать, если type === «чат», попробуйте так (type === «обычный», без сортировки) :

 arr.filter(item => {
  if (item.type === "normal") {
    return item
  }
  //sort array by referenceId and keeping last item

})
 

Комментарии:

1. Добро пожаловать в SO! Я немного смущен вашей логикой в filter обратном вызове. Какое отношение item.type === "normal" имеет остальная часть вашей спецификации?

2. только тип сортировки === «чат», если тип === «обычный», сортировки нет

Ответ №1:

Вы могли бы сделать сопоставление referenceId -> lastIndex , а затем посмотреть индекс в своем filter , чтобы сохранить только те индексы, которые соответствуют последнему для этого referenceId . Выполняется проверка, чтобы убедиться, что мы отфильтровываем только type: "chat" элементы. Временная сложность линейна.

 const arr = [
  { id: 1, referenceId: 1, type: "normal", name: "a" },
  { id: 2, referenceId: 1, type: "normal", name: "b" },
  { id: 3, referenceId: 3, type: "chat", name: "c" },
  { id: 4, referenceId: 4, type: "normal", name: "d" },
  { id: 5, referenceId: 5, type: "chat", name: "e" },
  { id: 6, referenceId: 3, type: "chat", name: "f" }
];

const lastIdxes = arr.reduce((a, e, i) => {
  a[e.referenceId] = i;
  return a;
}, {});
const result = arr.filter((e, i) => 
  e.type !== "chat" || i === lastIdxes[e.referenceId]
);
console.log(result); 

Ответ №2:

Вы можете использовать сокращение следующим образом,

 let arr = [
  { id: 1, referenceId: 1, type: "normal", name: "a" },
  { id: 2, referenceId: 2, type: "normal", name: "b" },
  { id: 3, referenceId: 3, type: "chat", name: "c" },
  { id: 4, referenceId: 4, type: "normal", name: "d" },
  { id: 5, referenceId: 5, type: "chat", name: "e" },
  { id: 6, referenceId: 3, type: "chat", name: "f" }
];

res = arr.reduce((prev, curr) => {
  index = prev.findIndex(item => item.referenceId === curr.referenceId);
  if(index > -1) {
    prev.splice(index, 1);
  }
  
  prev.push(curr);
  return prev;
}, []);
console.log(res); 

Ответ №3:

сортировка по идентификатору, как указано в названии этого вопроса, а затем отслеживание того, когда будут удалены дубликаты

 // sort by id and drop referenceId duplicates
const arr = [
  { id: 1, referenceId: 1, type: "normal", name: "a" },
  { id: 2, referenceId: 2, type: "normal", name: "b" },
  { id: 3, referenceId: 3, type: "chat", name: "c" },
  { id: 4, referenceId: 4, type: "normal", name: "d" },
  { id: 5, referenceId: 5, type: "chat", name: "e" },
  { id: 6, referenceId: 3, type: "chat", name: "f" }
];

arr.sort((a, b) => a.id > b.id ? 1 : -1);

const toDrop = [];
const mapper = {};
arr.forEach((curr, i) => {
    if (mapper[curr.referenceId] !== undefined) {
    toDrop.unshift(mapper[curr.referenceId]);
  }
  mapper[curr.referenceId] = i;
});

toDrop.forEach(i => {
    arr.splice(i, 1);
});

console.log(arr);