【问题标题】:Javascript merge/reduce same multi dimensional objectsJavascript合并/减少相同的多维对象
【发布时间】:2018-12-26 06:53:53
【问题描述】:

根据我的问题:https://stackoverflow.com/a/40661953/2392461,我用示例数据打开一个新问题。

我想合并/减少这个:

var array = [{
  'key1': {
    'key11': 0,
    'key12': 1
  },
  'key2': 0,
  'key3': {
    'key31': [1, 2],
    'key32': {
        'key321': 3,
        'key322': [1, 2]
    }
  },
  'key4': 'test'
  }, {
  'key1': {
    'key11': 1,
    'key12': 9
  },
  'key2': 2,
  'key3': {
    'key31': [4, 3],
    'key32': {
        'key321': 6,
        'key322': [8, 9]
    }
  },
  'key4': 'test'
  }, {
  'key1': {
    'key11': 3,
    'key12': 4
  },
  'key2': 7,
  'key3': {
    'key31': [3, 2],
    'key32': {
        'key321': 6,
        'key322': [7, 8]
    }
  },
  'key4': 'test'
}];

到这里:

{
  'key1': {
    'key11': [0, 1, 3],
    'key12': [1, 9, 4]
  },
  'key2': [0, 2, 7],
  'key3': {
    'key31': [[1, 2], [4, 3], [3, 2]],
    'key32': {
        'key321': [3, 6, 6],
        'key322': [[1, 2], [8, 9], [7, 8]]
    }
  },
  'key4': 'test'
}

@stasovlas 中带有 lodash 的 reduce 函数 (https://stackoverflow.com/a/40668315/2392461) 看起来不错,但我需要深入研究对象。

_.reduce(data, function(result, item) {
    var added = _.find(result, {
        key4: item.key4
    });
    if (_.isObject(added)) {
        //!! better to merge with new object and add result to array again to avoid mutable
        added = _.mergeWith(added, item, function(addedVal, itemVal, key) {
            if (key === 'key4') {
                return addedVal;
            }
            return _.concat(addedVal, itemVal);
        });
        return result;
    }
    return _.concat(result, item);
}, []);

这里的结果是一个合并的对象,只在对象的第 1 层。

[ { key1: [ [Object], [Object], [Object] ],
    key2: [ 0, 2, 7 ],
    key3: [ [Object], [Object], [Object] ],
    key4: 1 } ]

我不知道如何得到我的结果。我想我必须迭代每个对象 n 次。 n 是物体的深度。

这是正确的方法还是比我想象的更容易?

莫克你好

【问题讨论】:

  • key4 有什么特别之处?为什么它不是一个包含三个'test' 的数组?
  • 抱歉,我从另一个数组复制了一个结果。但我需要一个像“key4”这样的 ID 密钥

标签: javascript merge lodash javascript-objects reduce


【解决方案1】:

您可以通过迭代源对象的条目来合并每个级别,并创建一个新对象或一个数组来添加结果。继续处理子对象。

key4 获得特殊待遇。

function merge(target, source) {
    var singleKey = 'key4';
    Object.entries(source).forEach(([key, value]) => {
        if (value && typeof value === 'object' && !Array.isArray(value)) {
            merge(target[key] = target[key] || {}, value);
            return;
        }
        if (key === singleKey) {
            target[key] = value;
            return;
        }
        target[key] = target[key] || [];
        target[key].push(value);
    });
    return target;
}

var array = [{ key1: { key11: 0, key12: 1 }, key2: 0, key3: { key31: [1, 2], key32: { key321: 3, key322: [1, 2] } }, key4: "test" }, { key1: { key11: 1, key12: 9 }, key2: 2, key3: { key31: [4, 3], key32: { key321: 6, key322: [8, 9] } }, key4: "test" }, { key1: { key11: 3, key12: 4 }, key2: 7, key3: { key31: [3, 2], key32: { key321: 6, key322: [7, 8] } }, key4: "test" }],
    result = array.reduce(merge, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 谢谢,我现在不能检查,但明天。键必须是我的 ID 和字符串,相同的值也必须是一个数组。我将添加一个带有 unix 时间戳的 key5。完成减少数组后,我将使用它来生成时间序列图表
  • omg,这正是我想要的。现在我试着理解你的代码。这里到底发生了什么:target[key] = target[key] || [];?是吗:如果 target[key] 为空,那么 []?
  • 这会检查target[key] 是否为假,如undefined 并分配一个空数组。一个数组(尽管有一个或多个长度)是一个真实值,所以没有更多的赋值发生在默认值上。
  • 啊我不知道我可以直接使用带有变量赋值的短版本。
  • 谢谢你,这是艺术!!!如果我看到了……我想……好吧,这是有道理的,但我永远无法在脑海中押韵。
【解决方案2】:

我做了一些改进,它对于任何类型的问题都更加灵活。

function merge(target, source) {
    var fixedKeys = ['key1', 'key2', 'keyn'];

    Object.entries(source).forEach(([key, value]) => {
        if (value && value.toString() === '[object Object]') {
            merge(target[key] = target[key] || {}, value);
            return;
        }
        if (value && Array.isArray(value)) {
            merge(target[key] = target[key] || [], value);
            return;
        }
        if (fixedKeys.indexOf(key) !== -1) {
            target[key] = value;
            return;
        }
        target[key] = target[key] || [];
        target[key].push(value);
    });
    return target;
}

现在你可以合并/减少更深层次的值/数组/对象,没有从 JS 数组到对象的转换或其他方式,它是 JSON.stringify 兼容的。您可以设置一个只出现一次的键数组。

希望这不仅对我有帮助:)

【讨论】:

  • 太好了,您接受了我的回答作为您接受的答案,没有提及......然后接受它。如果感到被剥削。
  • 抱歉,这不是我的本意。我应该把它作为评论发布吗?
  • 发帖就好了。
猜你喜欢
  • 2017-05-09
  • 2020-10-29
  • 2019-08-02
  • 2017-06-24
  • 2019-07-30
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多