从对象数组中提取最小值/最大值,而无需了解属性名称

时间:2018-08-30 21:12:49

标签: javascript arrays aggregate

我想从集合的所有属性中提取最小和最大值:

int myClass::fun(myClass::myEnum e) {
    int result{};
    switch (e){
        case myEnum::a:{
            result = 0;
            break;
        }
        case myEnum::b:{
            result = 1;
            break;
        }
        default:
        {
           assert(false);
           break;
        }
    }
    return result;
}

我应该事先知道属性名称,我可以做类似的事情:

"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));

尽管有效,但在这里简单地使用for / forEach似乎过于繁琐-可能不是最有效的。相反,我正在寻找一种更干净,更原始的方法(首选ES6)来实现这一目标。例如,也许基于Array.prototype的整洁的lambda构造。最好不要使用lodash或下划线之类的库。

理想情况下如何改进这段代码,这样我就不必遍历集合中每个属性的每个对象?

相关问题,但绝对不相同:

2 个答案:

答案 0 :(得分:1)

如果您不介意使用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)

答案 1 :(得分:1)

使用reduce()for in循环的示例

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)