Подсчитать количество элементов в dict

#javascript

#javascript

Вопрос:

У меня простая проблема, но решение для меня непросто. В принципе, у меня действительно есть массив с объектами состояния в нем.

 status = [ {status:1, id:10},
           {status:2, id:11},
           {status:1, id:12}]
  

Теперь я хочу подсчитать все объекты со статусом 1, все объекты со статусом 2 за один раз. Итак, мой конечный результат должен быть примерно таким:

 [ [1,2], [2,1]]
  

У меня уже есть это, но последний шаг для меня всегда завершается неудачей:

 items = status.map(function(x){return x.status})
unique = new Set(items)
  

И тогда я застрял.

В python я знаю, как это сделать, но в данный момент это невозможно.

 // this is the python code 
items = [x["status"] for x in status]
[ [x, items.count(x)] for x in set(items)]
  

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

1. Обязательно ли в результате получается массив? Вы можете легко использовать reduce для достижения такой цели, и, на мой взгляд, имело бы смысл вернуть объект вместо этого: jsfiddle.net/5ks9ph1n

2. Объект тоже подойдет 🙂

Ответ №1:

Вы могли бы взять a Map и массив пар ключ / значение с Array.from .

Кстати, вам нужно переименовать global status во что-то другое, потому что window.status это строка a, зарезервированная для сообщений о состоянии пользовательского агента.

 var array = [{ status: 1, id: 10 }, { status: 2, id: 11 }, { status: 1, id: 12 }],
    result = Array.from(array.reduce(
        (m, { status }) => m.set(status, (m.get(status) || 0)   1),
        new Map
    ));

console.log(result);  

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

1. status.reduce is not a function

2. @Durga, откуда у вас ошибка? внутренняя status — это локальная переменная, внешняя — массив.

3. В Chrome. После изменения внешнего статуса на что-то другое это работает.

4. @NinaScholz запуск примера выдает ошибку. prntscr.com/msz37f Хотя решение абсолютно правильное, оно выдает TypeError

5. возможно, переименование поможет.

Ответ №2:

 const status = [
  {status:1, id:10},
  {status:2, id:11},
  {status:1, id:12}
];
const statuses = [];
const result = [];

status.map(s => {
    if (statuses.indexOf(s.status) === -1) {
    result.push([ s.status, status.filter(i => i.status === s.status ).length ]);
    statuses.push(s.status);
  }
});

console.log(result);
  

Ответ №3:

Поскольку объект также является принятым ответом (как указано в комментариях выше), вы также можете просто использовать reduce и переносить данные в новый объект:

 var arr = [ {status:1, id:10},
           {status:2, id:11},
           {status:1, id:12}];
           
console.log(
   arr.reduce((a, {status}) => {
  	if (a[status]) a[status]  ;
        else a[status] = 1;
        return a;
  }, {})
)  

Вы все еще можете сократить количество шагов для выполнения чего-либо, хотя приведенное выше довольно легко прочитать. если в «a» (который является пустым объектом в начале) статус уже существует, затем увеличьте его. В противном случае установите его равным единице и продолжайте, пока массив не будет полностью зациклен.

{status} (второй параметр) возвращает status ключевое значение текущего зацикленного объекта, эквивалентное item.status .

Ответ №4:

Вы можете просто использовать простой reduce , а затем использовать записи, чтобы получить ожидаемый формат 🙂

 const status = [ {status:1, id:10},
           {status:2, id:11},
           {status:1, id:12}];
           
const result = status.reduce((acc, {status}) => (acc[status] = (acc[status] || 0)   1, acc), {});
console.log(result);

const formattedResult = Object.entries(result)
console.log(formattedResult);

// If you need to remove the string format from the keys: 

const formattedResult2 = Object.entries(result).map(([k,v]) => [Number(k),v]);
console.log(formattedResult2);  

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

1. Выходные данные не являются массивом массивов, как описано в вопросе.

2. Обновлено. Хотя ожидаемый результат для меня довольно неестественный!