gpt4 book ai didi

javascript - 如何对具有多个属性的数组进行分组

转载 作者:行者123 更新时间:2023-12-05 02:33:58 26 4
gpt4 key购买 nike

我对在 Javascript 中分组有疑问。

我有一个如下所示的数组,其中每个项目保证只有 is_sweetis_spicyis_bitter 中的一个相等为 true:

const foodsData = [{
name: 'mie aceh',
is_sweet: false,
is_spicy: true,
is_bitter: false,
}, {
name: 'nasi padang',
is_sweet: false,
is_spicy: true,
is_bitter: false,
}, {
name: 'serabi',
is_sweet: true,
is_spicy: false,
is_bitter: false,
}, {
name: 'onde-onde',
is_sweet: true,
is_spicy: false,
is_bitter: false,
}, {
name: 'pare',
is_sweet: false,
is_spicy: false,
is_bitter: true,
}];

我想要的输出是根据第一个元素的 is_sweet、第二个元素的 is_bitter 和第三个元素的 is_spicy 对数组进行分组,如下所示:

[ 
[
{ name: 'serabi',
is_sweet: true,
is_spicy: false,
is_bitter: false },
{ name: 'onde-onde',
is_sweet: true,
is_spicy: false,
is_bitter: false }
],
[
{ name: 'pare',
is_sweet: false,
is_spicy: false,
is_bitter: true }
],
[
{ name: 'mie aceh',
is_sweet: false,
is_spicy: true,
is_bitter: false },
{ name: 'nasi padang',
is_sweet: false,
is_spicy: true,
is_bitter: false }
]
]

我尝试通过编写下面的代码来做到这一点

const isSweet = foodsData.filter(food => food.is_sweet);
const isBitter = foodsData.filter(food => food.is_bitter);
const isSpicy = foodsData.filter(food => food.is_spicy);
const newFood = [];
newFood.push(isSweet);
newFood.push(isBitter);
newFood.push(isSpicy);

有没有一种方法可以使用原始 Javascript 或 Lodash 获得相同的结果但代码更清晰?

最佳答案

您已经阐明每个项目只能具有三个属性之一 is_sweet/is_spicy/is_bitter等于true .

鉴于此假设,一种方法是我们可以根据数量值对项目进行分组 x.is_sweet*4 + x.is_spicy*2 + x.is_bitter*1对于项目 x .对于那些只有 is_bitter: true 的人,这个数量等于 1 , 2 对于只有 is_spicy: true 的项目, 4 对于只有 is_sweet: true 的项目.

根据该数量分组后,您可以使用 _.values摆脱由 _.groupBy 创建的 key :

_.values(_.groupBy(foodsData, x => x.is_sweet*4 + x.is_spicy*2 + x.is_bitter*1))

显然,您可以为谓词指定一个描述性名称:

const flavour = food => food.is_sweet*4 + food.is_spicy*2 + food.is_bitter*1;
let groupedFoods = _.values(_.groupBy(foodsData, flavour))

请注意,如果允许项目具有这三个键中的多个键为真,则上面的代码仍会给出合理的结果,因为您将拥有与 [is_sweet, is_spicy, is_bitter] 相关的八组。等于[0,0,0] , [0,0,1] , [0,1,0] , [0,1,1] , [1,0,0] , [1,0,1] , [1,1,0] , 和 [1,1,1] .

事后看来,我们不需要谓词 flavour为每个条目拉出一个数字 food ;根据上一段,如果它提取三个值,我们会很高兴 food.is_sweet , food.is_spicy , 和 food.is_bitter , 并将它们放在一个数组中。 Lodash 有 _.over为此,我们可以定义

const flavour = _.over([is_sweet, is_spicy, is_bitter]);

关于上述解决方案的可读性的几句话。

  • _.groupBy是比 reduce 更高层次的抽象- 类似(成员(member)或免费)功能;换句话说,后者的功能比问题中用例所需的功能强大得多,因此它们的表现力不如前者。事实上,_.groupBy很可能根据 reduce 来实现.这是一个残酷的实现来证明这是可能的:

    const groupBy = (things, f) => {
    return things.reduce((acc, item) => {
    if (acc[f(item)] == undefined)
    acc[f(item)] = [item];
    else
    acc[f(item)].push(item);
    return acc;
    }, {});
    }
    // both these give the same result:
    groupBy([1,2,3,4,4,4], x => x % 2 == 0); // mine
    _.groupBy([1,2,3,4,4,4], x => x % 2 == 0); // lodash's
  • 解决方案在文字上非常简短:它看起来多么“复杂”或“花哨”并不重要;一旦您习惯了这种做事方式(也就是正确的方式),您就会阅读代码。再看一遍:

    _.values(_.groupBy(foodsData, flavour))

    这已经相当可读了,但是如果你使用 lodash/fp 模块,你甚至可以改进它:

    _.values(_.groupBy(flavour, foodsData))

    这与下面的英文句子有多远?

    "get the values of the result of grouping by flavor the foods"

    说不可读就意味着否认事物的真实性。

  • 使用较低杠杆结构的较长解决方案,例如 for循环或(好一点)reduce -like 实用程序会强制您解析 代码。如果不仔细检查它们的 body ,您就无法理解这些溶液的作用。即使您决定拉取函数 (acc, item) => { … }退出 reduce 的通话并为其命名,以 input.reduce(<i>fun</i>, <i>acc</i>) 结尾你怎么给它起名字?它是一个在中间结果中将元素推到数组顶部的函数。除非在琐碎的用例中,否则您不会为这样满嘴的东西找到一个好名字。您只是将问题转移到其他地方。阅读这段代码的人仍然会感到困惑。

  • _.over也可能有点可怕:

    const flavour = _.over([is_sweet, is_spicy, is_bitter]);

    但实际上,你只是学习并接受什么,这需要付出什么代价_.over方法?我的意思是,这就像学习一门新语言,仅此而已。 And the explanation of _.over is fairly simple :

    _.over([iteratees=[_.identity]])

    Creates a function that invokes iteratees with the arguments it receives and returns their results.

    就是这么简单:_.over(['a', 'b', 'd'])({a: 1, b: 2, c: 3}) == [1, 2, undefined]

关于javascript - 如何对具有多个属性的数组进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70844485/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com