Извлекать минимальные / максимальные значения из массива объектов, не зная имен свойств - PullRequest
0 голосов
/ 31 августа 2018

Я хочу извлечь значения min и max из всех свойств коллекции:

"data": [
    {
        "food": 41000,
        "drinks": 60,
        "toys": 18961,
        "candy": 8740
    },
    {
        "food": 245,
        "abusive-usage": 96,
        "drinks": 5971,
        "candy": 12492,
        "somethingnew": 8
    },
    {
        "food": 365,
        "abusive-usage": 84,
        "toys": 22605,
        "candy": 9256,
        "somethingold": 1
    },
    {}
];

Если бы я знал заранее имена и свойства, я мог бы сделать что-то вроде:

const max = Math.max(...graph.datasets.urgency.map((x) => x.knownPropertyName));

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

С помощью следующего фрагмента я могу заставить это работать:

    let maxUrgency = 0;
    let minUrgency = 0;
    data.forEach((day) => {
        Object.keys(day).forEach((key, index) => {
            if (day[key] > maxUrgency) maxUrgency = day[key];
            if (day[key] < minUrgency) minUrgency = day[key];
        });
    });

Хотя это работает, кажется слишком громоздким - и, вероятно, не самым эффективным - просто использовать for / forEach здесь. Вместо этого я ищу более чистый, ванильный подход (предпочтительно ES6) для достижения этой цели. Например, аккуратная лямбда-конструкция, основанная на Array.prototype, возможно. Предпочтительно, я не хочу использовать библиотеку, такую ​​как lodash или подчеркивание.

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

Смежный вопрос, но точно не тот же самый:

Ответы [ 2 ]

0 голосов
/ 31 августа 2018

Пример использования reduce() и for in loop

var obj = {
    "data": [
        {
            "food": 41000,
            "drinks": 60,
            "toys": 18961,
            "candy": 8740
        },
        {
            "food": 245,
            "abusive-usage": 96,
            "drinks": 5971,
            "candy": 12492,
            "somethingnew": 8
        },
        {
            "food": 365,
            "abusive-usage": 84,
            "toys": 22605,
            "candy": 9256,
            "somethingold": 1
        }
    ]
};

//max of each property

var res = obj.data.reduce((acc, c) => {

    for (let p in c) {
        if (c[p] > (acc[p] || 0)) acc[p] = c[p];
    }

    return acc;

}, {})

console.log(res)

//absolute max and min

var res = obj.data.reduce((acc, c) => {

    for (let p in c) {
        if (c[p] > acc[1] ) acc[1] = c[p];
        if (c[p] < acc[0] ) acc[0] = c[p];
    }
return acc
}, [Infinity,0])


console.log(res)
0 голосов
/ 31 августа 2018

Если вы не против сделать какой-нибудь ES2017, есть Object.values(). Используйте его вместе с array.reduce().

const data = [{
    "food": 41000,
    "drinks": 60,
    "toys": 18961,
    "candy": 8740
  },
  {
    "food": 245,
    "abusive-usage": 96,
    "drinks": 5971,
    "candy": 12492,
    "somethingnew": 8
  },
  {
    "food": 365,
    "abusive-usage": 84,
    "toys": 22605,
    "candy": 9256,
    "somethingold": 1
  },
  {}
]

const values = data.reduce((c, v) => [...c, ...Object.values(v)], [])
const min = Math.min(...values)
const max = Math.max(...values)

console.log(min, max)

Альтернативно, array.map() вместе с array.concat() может использоваться вместо array.reduce().

const data = [{
    "food": 41000,
    "drinks": 60,
    "toys": 18961,
    "candy": 8740
  },
  {
    "food": 245,
    "abusive-usage": 96,
    "drinks": 5971,
    "candy": 12492,
    "somethingnew": 8
  },
  {
    "food": 365,
    "abusive-usage": 84,
    "toys": 22605,
    "candy": 9256,
    "somethingold": 1
  },
  {}
]

const valueArrays = data.map(v => Object.values(v))
const values = Array.prototype.concat.call(...valueArrays)
const min = Math.min(...values)
const max = Math.max(...values)

console.log(min, max)
...