使用lodash转换集合

时间:2016-01-17 11:42:36

标签: javascript json collections lodash

我有一个查询给我Json数据;例如,我有以下Json

{
"salesInvoices":

    [
    {
        "id": "1",
        "salesInvoiceLines":
        [
            {
                "ItemCode": "Apple",
                "UnitCode": "piece",
                "Quantity": "10"
            },
            {
                "ItemCode": "Orange",
                "UnitCode": "box",
                "Quantity": "2"
            }
        ]
    },
    {
        "id": "2",
        "salesInvoiceLines":
        [
            {
                "ItemCode": "Apple",
                "UnitCode": "piece",
                "Quantity": "20"
            },
            {
                "ItemCode": "Orange",
                "UnitCode": "piece",
                "Quantity": "21"
            },
            {
                "ItemCode": "Orange",
                "UnitCode": "box",
                "Quantity": "1"
            }
        ]
    }
    ]

}

我想按项目 - 单位对将数据分组为以下格式:

[
  { item : 'Apple', unit : 'piece', totalQuantity : 30 },
  { item : 'Orange', unit : 'piece', totalQuantity : 21 },
  { item : 'Orange', unit : 'box', totalQuantity : 3 }
]

我使用lodash库累了以下代码,但它不起作用

   var sumQuantity = function(total, item){
        return total + item.Quantity
    }

    var transformList = function(line){
        return _.map(line.SalesInvoiceLines, function(invoice){
            return _.map(invoice, function(line){
                return {
                    item: line.ItemCode,
                    unit: line.UnitCode,
                    totalQuantity: _.reduce(line.Quantity, sumQuantity, 0)
                }
            })
        });
    };

    var groupedList = _.groupBy(data.d.results, function(line) {
        return line.ItemCode + line.UnitCode;
    });

    var list = _.chain(groupedList)
    .map(transformList)
    .flatten()
    .value();

如何获得上述结果?

3 个答案:

答案 0 :(得分:2)

对不起,我不能给你一个具体的工作实例。根据我的看法,您的代码中存在以下概念错误:

  1. 我猜最初的groupBy语句是错误的。假设data.d.results与您发布的示例JSON相同,那么您无法在那里访问line.ItemCode + line.UnitCode;。相反,您只需为salesInvoices进行一次迭代。

  2. 您有一级_.map次来电不需要:

    return _.map(line.SalesInvoiceLines, function(invoice){ return _.map(invoice, function(line){

  3. =>发票已经是发票。迭代发票的属性是没有意义的(调用它们line也没有意义。)

    1. totalQuantity: _.reduce(line.Quantity, sumQuantity, 0)中一样使用_.reduce()是没有意义的,因为line.Quantity已经是原始数字。你不能“减少”那个。
    2. 我的建议是:

      1. 获得正确的基本转换并尝试将所有发票提取为平面数组
      2. 然后你可以_.reduce()将这个数组转换为一个中间对象,其中的键包含“line.ItemCode + line.UnitCode”,指向你想要的形式的对象,例如: { item : 'Apple', unit : 'piece', totalQuantity : 30 }。在每次reduce迭代时,你只需要确定这个“唯一键”,测试对象是否已经存在,如果不是你用totalQuantity = 1创建它,否则你只需增加totalQuantity。
      3. finnaly,在步骤2的中间结果上调用_.values()。

答案 1 :(得分:1)

// Input
var data = {
    "salesInvoices": [{
        "id": "1",
        "salesInvoiceLines": [{
            "ItemCode": "Apple",
            "UnitCode": "piece",
            "Quantity": "10"
        }, {
            "ItemCode": "Orange",
            "UnitCode": "box",
            "Quantity": "2"
        }]
    }, {
        "id": "2",
        "salesInvoiceLines": [{
            "ItemCode": "Apple",
            "UnitCode": "piece",
            "Quantity": "20"
        }, {
            "ItemCode": "Orange",
            "UnitCode": "piece",
            "Quantity": "21"
        }, {
            "ItemCode": "Orange",
            "UnitCode": "box",
            "Quantity": "1"
        }]
    }]

}
//Output
/*
[
  { item : 'Apple', unit : 'piece', totalQuantity : 30 },
  { item : 'Orange', unit : 'piece', totalQuantity : 21 },
  { item : 'Orange', unit : 'box', totalQuantity : 3 }
]
*/
// Code
_.chain(_.flatten(_.map(data.salesInvoices, 'salesInvoiceLines')))
    .reduce(function(output, curr) {
        output[curr.ItemCode + '_' + curr.UnitCode] = output[curr.ItemCode + '_' + curr.UnitCode] ? output[curr.ItemCode + '_' + curr.UnitCode] + parseInt(curr.Quantity) : parseInt(curr.Quantity);
        return output;
    }, {})
    .reduce(function(result, value, key) {
        result.push({
            item: key.split('_')[0],
            unit: key.split('_')[1],
            totalQuantity: value
        });
        return result;
    }, []).value();

答案 2 :(得分:0)

我能够使用以下代码完成:

    var invoicelines = [];
    var lines = _.map(data, 'SalesInvoiceLines');

    var getLines = lines.forEach(function (entry){
        var l = entry.results;
        l.forEach(function (line){
            invoicelines.push(line);
        })
    });

    var list = _.chain(invoicelines)
       .groupBy(function(sll) {
            return sll.ItemCode + sll.UnitCode;
        })
        .map(function(value, key) {
            return [key, _.reduce(value, function(result, currentObject) {
                return {
                    Item: currentObject.ItemCode,
                    Unit: currentObject.UnitCode,
                    Quantity: result.Quantity + currentObject.Quantity
                }
            }, {
                Quantity: 0
            })];
        })
        .object()
        .sortBy(function(item) {
           return item.Quantity
        })
        .value();