как получить топ X через фильтр, в массиве объектов (Javascript) - PullRequest
0 голосов
/ 19 сентября 2018
Требование

состоит в том, чтобы получить верхний X score (s) для КАЖДОГО «пользователя» в массиве объектов.

массив объектов уже отсортирован пользователем по количеству баллов.

, например, если мы ищем «Топ-3», и в массиве для пользователя есть 4 строки"barney" - затем верните первые 3 элемента из массива для пользователя "Barney".

другой пример: если это "Top 3", мы после, а у пользователя 2элементы в массиве - затем вернуть эти 2 элемента.

вот пример, где я хочу TOP 3:

var users = [
 { user: 'barney', score: 39},
 { user: 'barney', score: 37},
 { user: 'barney', score: 36},
 { user: 'barney', score: 36},
 { user: 'fred', score: 40},  
 { user: 'fred', score: 22},
 { user: 'wilma', score: 40},
 { user: 'wilma', score: 40}
];

, поэтому в этом примере результат должен быть:

[
 { user: 'barney', score: 39},
 { user: 'barney', score: 37},
 { user: 'barney', score: 36},
 { user: 'fred', score: 40},
 { user: 'fred', score: 22},
 { user: 'wilma', score: 40},
 { user: 'wilma', score: 40}
];

Ответы [ 2 ]

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

Если предположить, что коллекция users уже отсортирована по имени и количеству баллов, вы можете просто добиться этого, используя Array # filter .

const getTop = (users, top, counts = {}) => 
  users.filter(({ user }) => (counts[user] = (counts[user] || 0) + 1) <= top);

var users = [
  { user: 'barney', score: 39},
  { user: 'barney', score: 37},
  { user: 'barney', score: 36},
  { user: 'barney', score: 36},
  { user: 'fred', score: 40},  
  { user: 'fred', score: 22},
  { user: 'wilma', score: 40},
  { user: 'wilma', score: 40}
];

const getTop = (users, top, counts = {}) => 
  users.filter(({ user }) => (counts[user] = (counts[user] || 0) + 1) <= top);

console.log('TOP 1', getTop(users, 1));
console.log('TOP 2', getTop(users, 2));
console.log('TOP 3', getTop(users, 3));
.as-console-wrapper{min-height:100%;}
0 голосов
/ 19 сентября 2018

Это возможно без lodash, поэтому это также возможно с lodash.

Разделить исходный массив пользователем, использовать slice, чтобы сохранить первый x, объединить все обратно в 1 массив.

var users = [
 { user: 'barney', score: 39},
 { user: 'barney', score: 37},
 { user: 'barney', score: 36},
 { user: 'barney', score: 36},
 { user: 'fred', score: 40},  
 { user: 'fred', score: 22},
 { user: 'wilma', score: 40},
 { user: 'wilma', score: 40}
];
var x = 3;

var names = users.reduce((acc, n) => {
  acc.add(n.user);
  return acc;
}, new Set());
var groups = [...names].reduce((acc, n) => {
  acc.push(users.filter(m => m.user === n));
  return acc;
}, []);
groups = groups.map(n => n.slice(0, x));
var result = groups.reduce((acc, n) => {
  acc.push(...n);
  return acc;
}, []);
console.log(result);
...