Фильтровать верхние n значений свойства в массиве объектов на основе других значений свойств в Javascript

#javascript #arrays #d3.js

#javascript #массивы #d3.js

Вопрос:

У меня есть массив объектов, похожих на

 var array = [
{year: 2000, rating: 1, count: 20},
{year: 2000, rating: 1, count: 10},
{year: 2000, rating: 1, count: 5},
{year: 2000, rating: 2, count: 45},
{year: 2000, rating: 2, count: 20},
{year: 2000, rating: 2, count: 17},
{year: 2001, rating: 1, count: 100},
{year: 2001, rating: 1, count: 46},
{year: 2001, rating: 1, count: 30},
{year: 2001, rating: 2, count: 15},
{year: 2001, rating: 2, count: 10},
{year: 2001, rating: 2, count: 5}]
 

Я хотел бы иметь возможность фильтровать этот массив по верхним n значениям в графе по годам и рейтингу. Я думаю, что slice(0,5) сработал бы, но я новичок в javascript и не могу понять, как перебирать массив на основе года и рейтинга.

Я бы ожидал, что результат для топ-2 будет следующим:

 [
    {year: 2000, rating: 1, count: 20},
    {year: 2000, rating: 1, count: 10},
    {year: 2000, rating: 2, count: 45},
    {year: 2000, rating: 2, count: 20},
    {year: 2001, rating: 1, count: 100},
    {year: 2001, rating: 1, count: 46},
    {year: 2001, rating: 2, count: 15},
    {year: 2001, rating: 2, count: 10}
]
 

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

1. Можете ли вы поделиться своим ожидаемым результатом для предоставленных данных?

2. Конечно! Итак, если бы я хотел получить объекты с 2 верхними значениями для count, я бы ожидал увидеть: var new_array = [ {год: 2000, рейтинг: 1, количество: 20}, {год: 2000, рейтинг: 1, количество: 10}, {год: 2000, рейтинг: 2, количество: 45}, {год: 2000, рейтинг: 2, количество: 20}, {год: 2001, рейтинг: 1, количество: 100}, {год: 2001, рейтинг: 1, количество: 46}, {год: 2001, рейтинг: 2, количество: 15}, {год выпуска: 2001, рейтинг: 2, количество: 10}]

3. Всегда ли входные данные сортируются по year и rating ?

4. Да, я смог отсортировать массив в соответствующем порядке.

5. И должен ли порядок объектов в выходном массиве соответствовать порядку объектов из исходного массива? например: может {...... count: 10} быть раньше {...... count: 15} в результате?

Ответ №1:

Вы можете сгруппировать по year и rating (используя year-rating ключи), используя .reduce() и Map , чтобы у вас был массив объектов, которые указывают количество и индекс, с которым встречается каждый объект:

 2000-1: [{count: 20, idx: 0}, {count: 10,idx: 1}, {count: 5, idx: 2}, ...],
2000-2: [{count: 45, idx: 4}, ...],
2001-1: [...],
2001-2: [...]
 

после того, как у вас есть карта вышеупомянутой структуры, вы можете отсортировать каждый массив значений по количеству в порядке возрастания и использовать .slice(-n) для получения верхних (последних) n элементов. Получив верхние элементы, вы можете сопоставить top массивы значений каждого значения с их фактическими значениями объектов, используя idx свойство. Однако прежде чем вы это сделаете, вы можете выполнить сортировку по idx , чтобы сохранить относительный порядок:

 const arr = [ {year: 2000, rating: 1, count: 20}, {year: 2000, rating: 1, count: 10}, {year: 2000, rating: 1, count: 5}, {year: 2000, rating: 2, count: 45}, {year: 2000, rating: 2, count: 20}, {year: 2000, rating: 2, count: 17}, {year: 2001, rating: 1, count: 100}, {year: 2001, rating: 1, count: 46}, {year: 2001, rating: 1, count: 30}, {year: 2001, rating: 2, count: 15}, {year: 2001, rating: 2, count: 10}, {year: 2001, rating: 1, count: 5} ];

const n = 2;
const res = Array.from(arr.reduce((acc, {year, rating, count}, idx) => {
  const key = `${year}-${rating}`;
  const curr = acc.get(key) || []; 
  return acc.set(key, [...curr, {count, idx}])
}, new Map).values(), group => group.sort((a, b) => a.count - b.count).slice(-n)).flatMap(
  top => top.sort((a, b) => a.idx - b.idx).map(({idx}) => arr[idx])
);
console.log(res);