Фильтрация похожих идентификаторов по их последней версии

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

    const data = [
        {
        id: 1,
        version: 1
        },
        {
        id: 1,
        version: 2
        },
        {
        id: 1,
        version: 3
        },
        {
        id: 2,
        version: 1
        },
        {
        id: 3,
        version: 1
        },
        {
        id: 3,
        version: 2
        }
    ];

После фильтра должно быть:

    const data = [
        {
        id: 1,
        version: 1
        },
        {
        id: 2,
        version: 1
        },

        {
        id: 3,
        version: 2
        }
    ];

Каков наилучший способ сделать этот фильтр с меньшей сложностью/порядком? использование lodash разрешено.

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

Почему версия id 1 — 1, а версия id 3 — 2?

Hassan Imam 13.02.2023 07:10
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел "Заголовок" в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
Как React Helmet спасает меня при разделении файлов CSS?
Как React Helmet спасает меня при разделении файлов CSS?
Многие новички могут столкнуться с проблемой, когда одна страница с CSS наследует свойства от другой страницы с другим CSS. У меня было много проблем,...
1
1
63
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Это кажется достаточно эффективным: сортировка по идентификатору и версии за один проход, затем вы можете просто отфильтровать до последнего экземпляра каждого идентификатора, потому что это будет тот, у которого самый высокий номер версии. Конечно, если ваши данные предварительно отсортированы, вы можете сразу перейти к самой интересной части; Я переупорядочил исходные данные здесь, чтобы показать, как работает сортировка:

const latestVersions = d => {
  // sort by ID and version:
  d = d.sort((a, b) => {
    if (a.id === b.id) {
      return a.version - b.version
    } else {
      return a.id - b.id
    }
  }).filter((a, i) => {
    // only return elements that aren't followed by another with the same ID:
    return d[i + 1]?.id !== a.id
  })

  return d
}

const data = [{
    id: 1,
    version: 2
  },
  {
    id: 2,
    version: 1
  },
  {
    id: 3,
    version: 2
  },
  {
    id: 1,
    version: 1
  },

  {
    id: 1,
    version: 3
  },
  {
    id: 3,
    version: 1
  }
];

console.info(latestVersions(data))

Не по теме: можно .sort((a, b) => a.id - b.id || a.version - b.version)

Thomas 13.02.2023 07:44

Истинный! Я думаю, что так читать немного сложнее, но это действительно работает.

Daniel Beck 13.02.2023 07:51
Ответ принят как подходящий

С помощью lodash сгруппируйте по id, затем сопоставьте и возьмите объект с максимальным version из каждой группы.

Примечание. _.groupBy преобразует массив в объект, используя id в качестве ключа, и, поскольку вы используете целочисленные идентификаторы, порядок будет меняться в соответствии с числовыми значениями id. Если это проблема, см. второе решение.

const { map, groupBy, maxBy } = _

const data = [{"id":1,"version":1},{"id":1,"version":2},{"id":1,"version":3},{"id":2,"version":1},{"id":3,"version":1},{"id":3,"version":2}]

const result = map(
  groupBy(data, 'id'),
  g => maxBy(g, 'version')
)

console.info(result)
<script src = "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity = "sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ= = " crossorigin = "anonymous" referrerpolicy = "no-referrer"></script>

Vanilla JS, уменьшите массив до карты. Для каждого элемента проверьте, существует ли он на карте, и если его нет или его версия больше, чем версия на карте, установите текущий объект для этого id. Преобразуйте значения карты обратно в массив, используя Array.from().

Примечание. Использование карты сохраняет исходный порядок элементов массива.

const data = [{"id":1,"version":1},{"id":1,"version":2},{"id":1,"version":3},{"id":2,"version":1},{"id":3,"version":1},{"id":3,"version":2}]

const result = Array.from(data.reduce((acc, o) =>
  acc.has(o.id) && acc.get(o.id).version >= o.version
    ? acc
    : acc.set(o.id, o)
, new Map()).values())

console.info(result)

Вы можете попробовать следующий подход:

  • Создайте объект с ключом в качестве идентификатора и значением в качестве версии.
    • Это автоматически сохранит последнее значение для данной пары ключ-значение.
  • Создайте цикл и снова создайте объекты
    • { id: key, version: value }

const data = [{"id":1,"version":1},{"id":1,"version":2},{"id":1,"version":3},{"id":2,"version":1},{"id":3,"version":1},{"id":3,"version":2}]

const map = data.reduce(
  (acc, {id, version}) => ({ ...acc, [id]: version}),
  {}
)
const result = Object.entries(map).map(([k, v]) => ({id: k, version: v}))

console.info(result)

Другие вопросы по теме