Сортировать свойства объекта по значению и сохранить значения

1

Я создал массив имен продуктов, которые имеют дубликаты данных. Используя:

listFoodnames.forEach(x => {
  counts[x] = (counts[x] || 0) + 1;
});

Я могу подсчитать, сколько раз каждый элемент существует в массиве.

С помощью:

Object.keys(counts).sort((a, b) => counts[b]-counts[a])

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

Как я могу это решить?

$('document').ready(function() {
  var listFoodnames = ["Batteries", "Bread", "Milk", "Bread", "Milk", "Milk"]
  var counts = {};

  listFoodnames.forEach(x => {
    counts[x] = (counts[x] || 0) + 1;
  });

  console.log(counts) //LOGS EACH ITEM AS PROPERTY AND OCCURRENCES AS VALUE
  
  var sortedCounts = Object.keys(counts).sort((a, b) => counts[b]-counts[a])
  
  console.log(sortedCounts) //LOSES VALUES
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  • 0
    Я думаю, что словари не заказаны. Вы можете сохранить другой массив отсортированных значений?
Теги:

3 ответа

4
Лучший ответ

К сожалению, свойства объекта не гарантируются для заказа по спецификации. Вместо этого вы можете попробовать использовать массив объектов.

Также обратите внимание, что reduce является более подходящим, чем forEach когда вы комбинируете элементы в массиве в один объект.

const listFoodnames = ["Batteries", "Bread", "Milk", "Bread", "Milk", "Milk"];
const counts =
  Object.values(
    listFoodnames.reduce((a, foodName) => {
      if (!a[foodName]) a[foodName] = { foodName, count: 0 };
      a[foodName].count++;
      return a;
    }, {})
  );
counts.sort((a, b) => a.count - b.count);
console.log(counts);
  • 0
    object properties are not guaranteed to be ordered, per the spec. С ES6 это изменилось.
2

Вместо

var sortedCounts = Object.keys(counts).sort((a, b) => counts[b] - counts[a]);

использование

var sortedCounts = Object.entries(counts).sort(([keyA, a], [keyB, b]) => b - a);

Затем вы можете сопоставить каждую запись [key, value] с новым объектом:

console.log(sortedCounts.map(([key, value]) => ({[key]: value})));

Результат будет выглядеть так:

[
  {
    "Milk": 3
  },
  {
    "Bread": 2
  },
  {
    "Batteries": 1
  }
]

Обратите внимание, что невозможно получить что-то вроде

{
  "Milk": 3,
  "Bread": 2,
  "Batteries": 1
}

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

  • 0
    Note, that it is impossible to get something like , с ES6, это не так, сейчас ..
1

Все, кто ответил, неправильно сказали → dictionaries are not ordered

Это на самом деле не так, ES6 изменил спецификацию и сказал, что словарь заказан. Хотя до того, как порядок ES6 не был указан, большинство браузеров даже заказали заказ. Заказ, кстати, - порядок вставки. Заказ также будет работать при сериализации, например. JSON.parse/JSON.stringify.

Поэтому, используя эти знания, мы можем сделать результат в формате вашего после, отсортированного объекта.

пример ниже.

var listFoodnames = ["Batteries", "Bread", "Milk", "Bread", "Milk", "Milk"]
var counts = {};

listFoodnames.forEach(x => {
  counts[x] = (counts[x] || 0) + 1;
});

console.log(counts) //LOGS EACH ITEM AS PROPERTY AND OCCURRENCES AS VALUE

const sortedCount = 
  Object.entries(counts).sort((a,b) => b[1] - a[1]).
  reduce((a,v) => (a[v[0]] = v[1], a), {});

console.log(sortedCount);  

Ещё вопросы

Сообщество Overcoder
Наверх
Меню