Javascript无法将具有2个值的对象分组

问题描述 投票:0回答:2

我有这个对象数据:

[ RowDataPacket {
    id: 59,
    steamid: '76561198220437096',
    product_id: 23,
    status: 1,
    date: 2017-12-18T17:27:19.000Z,
    message: null,
    name: 'CS.MONEY',
    amount: 100,
    website: 'csgo500' },
  RowDataPacket {
    id: 60,
    steamid: '76561198220437096',
    product_id: 24,
    status: 1,
    date: 2017-12-18T17:27:19.000Z,
    message: null,
    name: 'CS.MONEY',
    amount: 250,
    website: 'csgo500' },
  RowDataPacket {
    id: 61,
    steamid: '76561198220437096',
    product_id: 23,
    status: 1,
    date: 2017-12-18T17:27:19.000Z,
    message: null,
    name: 'CS.MONEY',
    amount: 100,
    website: 'csgo500' },
  RowDataPacket {
    id: 62,
    steamid: '76561198345348530',
    product_id: 6,
    status: 1,
    date: 2017-12-18T20:05:55.000Z,
    message: null,
    name: 'wal gruche',
    amount: 100,
    website: 'csgoatse' }

我试图用steamid和网站对这些数据进行排序,我设法只对这个值进行排序,如下所示:

    var groupedOrders = {};
    row.forEach(function(item){
                    var list = groupedOrders[item.steamid];

                    if(list){
                        list.push(item);
                    } else{
                       groupedOrders[item.steamid] = [item];
                    }
                });

我的想法是制作二维数组但由于某种原因我不能这样做:

var list = groupedOrders[item.steamid][item.website];

它抛出一个错误“无法读取属性...未定义”

现在我的代码看起来像这样:

 var groupedOrders = {};
            row.forEach(function(item){
                var list = groupedOrders[item.steamid][item.website];

                if(list){
                    list.push(item);
                } else{
                   groupedOrders[item.steamid][item.website] = [item];
                }
            });

您有任何想法如何解决此错误?

javascript arrays sorting object
2个回答
0
投票

问题是var list = groupedOrders[item.steamid][item.website]实际上在说:

var temp = groupedOrders[item.steamid];
var list = temp[item.website];

groupedOrders[item.steamid]没有进入,所以第一线将temp设置为undefined。第二行尝试索引到undefined,这是一个错误。

您必须将代码拆分出来并基本上完成整个一键分组两次:

var outerList = groupedOrders[item.steamid];
if (!outerList)
    outerList = groupedOrders[item.steamid] = {};
var innerList = outerList[item.website];
if (innerList)
    innerList.push(item);
else
    outerList[item.website] = [item];

(我没有测试过这段代码但它的形状是正确的。)


0
投票

以下工作通过为作为参数提供的每个字段创建递归groupBy分组函数。

然后逐个调用这些动态创建的groupBy函数,从提供的数据开始传递结果。

每个groupBy函数实例都会创建一个对象,并为其添加与要分组的字段的键值对应的属性。

通过连续调用这些groupBy函数,我们创建了一个逐渐更多嵌套的对象树,每个连续级别的组使用符号标记为组。

最终结果是对象的嵌套(树!),其键对应于用于在该级别进行索引的字段。

最后,我们将巢展平,最终的顺序是可见的。

const flatten = o => Object.values(o).reduce((acc, c) => (Array.isArray(c) ? [...acc, ...c] : typeof c === 'object' ? [...acc, ...flatten(c)] : [...acc, c]), []);
const flow = (...fns) => data => fns.reduce((acc, c) => c(acc), data);
const GROUP = Symbol('group');
const asGroup = (result = []) => ((result[GROUP] = true), result);
const isGroup = o => o[GROUP];

const groupBy = field => (data, key) =>
    data.reduce((acc, c) => 
        ((key = c[field]), (acc[key] ? 
            (acc[key].push(c), acc) : 
                ((acc[key] = asGroup([c])), acc))), {});

const recurse = (test) => (transform) => o =>
    test(o)
        ? transform(o)
        : Object.entries(o).reduce(
              (acc, [k, v]) => (test(v) ? 
                  ((acc[k] = transform(v)), acc) : 
                  ((acc[k] = recurse(test)(transform)(v)), acc)), {});
                  
const group = (...fields) => flow(...fields.map(flow(groupBy, recurse(isGroup))), flatten);

const rows = asGroup([
    {
        id: 0,
        steamid: '2',
        website: 'a'
    },
    {
        id: 1,
        steamid: '2',
        website: 'b'
    },
    {
        id: 2,
        steamid: '2',
        website: 'a'
    },
    {
        id: 3,
        steamid: '1',
        website: 'b'
    },
    {
        id: 4,
        steamid: '0',
        website: 'b'
    }
]);
console.log(JSON.stringify(group('steamid', 'website')(rows), null, 2));
© www.soinside.com 2019 - 2024. All rights reserved.