合并和重新排序两个对象数组

时间:2015-06-13 07:39:49

标签: javascript arrays object javascript-objects

我正在试图弄清楚如何合并两个对象数组。这就是我需要做的事情:

  • field属性是每个对象的唯一标识符
  • 输出只需要在originalArray
  • 中列出对象
  • 需要维护localStorageArray的订单,并注意以前的要求(订单应为:barfoobaz
  • 输出需要包含来自localStorageArray的以下属性值:hiddenwidthfield是一个给定项,因为它是标识符)
  • originalArray的所有其他属性需要在输出中维护

这是我对它的嘲笑:

outputArray.forEach(function(originalItem){
    localStorageArray.forEach(function(localItem){
        if(originalItem.field === localItem.field){
            originalItem.hidden = localItem.hidden;
            originalItem.width = localItem.width;
        }
    });
});  

Full JS Fiddle

我能够很好地获得这些属性,但是根据localStorageArray我对如何重新排序有点迷失。我首先考虑在前一组.forEach()函数中这样做,但后来我认为不要弄乱forEach循环中的顺序,因为我认为这可能会弄乱一些东西。

对我的解决方案有任何建议吗?

以下是我的数组:

var originalArray = [{
        field: "foo",
        hidden: true,
        sortable: false,
        template: "<div>#=text#</div>",
        width: "20px",
        propA: "a",
        propB: "b"
    }, {
        field: "bar",
        hidden: false,
        sortable: false,
        template: "",
        width: "20%",
        propC: "C"
    }, {
        field: "baz",
        hidden: false,
        sortable: true,
        template: "<span>#=text#</span>",
        int: 3
    }];

var localStorageArray = [{
        field: "bar",
        hidden: false,
        sortable: false,
        width: "100px"
    }, {
        field: "foo",
        hidden: true,
        sortable: false,
        template: "<div>#=text#</div>",
        width: "40px"
    }, {
        field: "boo",
        hidden: true,
        sortable: true,
        template: "<div>Boo: #=text#</div>",
        width: "200px"
    }, {
        field: "baz",
        hidden: true,
        template: "baz:#=text#",
        width: "20px"
    }];

这是我想要的输出:

var desiredArray = [{
        field: "bar",
        hidden: false,
        sortable: false,
        template: "",
        width: "100px",
        propC: "C"
    }, {
        field: "foo",
        hidden: true,
        sortable: false,
        template: "<div>#=text#</div>",
        width: "40px",
        propA: "a",
        propB: "b"
    }, {
        field: "baz",
        hidden: true,
        sortable: true,
        template: "<span>#=text#</span>",
        width: "20px",
        int: 3
    }];

2 个答案:

答案 0 :(得分:1)

检查这个小提琴:http://jsfiddle.net/j2u2hhk6/

你实际上可以这样做:

var outputArray = [];

localStorageArray.forEach(function(localItem){
    originalArray.forEach(function(originalItem){
        if(originalItem.field === localItem.field){
            var item = JSON.parse(JSON.stringify(originalItem));
            item.hidden = localItem.hidden;
            item.width = localItem.width;
            outputArray.push(item);
        }
    });
});

答案 1 :(得分:1)

以下是使用ES6方法的示例。

&#13;
&#13;
/*global document, console, expect */
(function () {
    'use strict';

    var originalArray = [{
            field: 'foo',
            hidden: true,
            sortable: false,
            template: '<div>#=text#</div>',
            width: '20px',
            propA: 'a',
            propB: 'b'
        }, {
            field: 'bar',
            hidden: false,
            sortable: false,
            template: '',
            width: '20%',
            propC: 'C'
        }, {
            field: 'baz',
            hidden: false,
            sortable: true,
            template: '<span>#=text#</span>',
            int: 3
        }],
        localStorageArray = [{
            field: 'bar',
            hidden: false,
            sortable: false,
            width: '100px'
        }, {
            field: 'foo',
            hidden: true,
            sortable: false,
            template: '<div>#=text#</div>',
            width: '40px'
        }, {
            field: 'boo',
            hidden: true,
            sortable: true,
            template: '<div>Boo: #=text#</div>',
            width: '200px'
        }, {
            field: 'baz',
            hidden: true,
            template: 'baz:#=text#',
            width: '20px'
        }],
        desiredArray = [{
            field: 'bar',
            hidden: false,
            sortable: false,
            template: '',
            width: '100px',
            propC: 'C'
        }, {
            field: 'foo',
            hidden: true,
            sortable: false,
            template: '<div>#=text#</div>',
            width: '40px',
            propA: 'a',
            propB: 'b'
        }, {
            field: 'baz',
            hidden: true,
            sortable: true,
            template: '<span>#=text#</span>',
            width: '20px',
            int: 3
        }],
        outputArray = [],
        pre = document.getElementById('out'),
        equalField = function (originalElement) {
            return originalElement.field === this.field;
        };

    localStorageArray.reduce(function (acc, localElement) {
        var original = originalArray.find(equalField, localElement),
            shallowCopy;

        if (original) {
            shallowCopy = Object.assign({}, original);
            shallowCopy.hidden = localElement.hidden;
            shallowCopy.width = localElement.width;
            acc.push(shallowCopy);
        }

        return acc;
    }, outputArray);

    try {
        expect(outputArray).to.eql(desiredArray);
        pre.textContent = 'outputArray is equal to desiredArray\n\n';
    } catch (e) {
        console.error(e);
        pre.textContent = 'outputArray is not equal to desiredArray\n\n';
    }

    pre.textContent += JSON.stringify(outputArray, null, 2);
}());
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.32.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.min.js"></script>
<pre id="out"></pre>
&#13;
&#13;
&#13;

更新:根据您的新评论和数据,这可能是一个解决方案。

&#13;
&#13;
var originalArray = [{
        field: "foo",
        hidden: true,
        sortable: false,
        template: "<div>#=text#</div>",
        width: "20px",
        propA: "a",
        propB: "b"
    }, {
        field: "bee",
        hidden: true,
        sortable: false,
        template: "=#text#",
        int: 4
    }, {
        field: "bar",
        hidden: false,
        sortable: false,
        template: "",
        width: "20%",
        propC: "C"
    }, {
        field: "baz",
        hidden: false,
        sortable: true,
        template: "<span>#=text#</span>",
        int: 3
    }],
    localStorageArray = [{
        field: "bar",
        hidden: false,
        sortable: false,
        width: "100px"
    }, {
        field: "foo",
        hidden: true,
        sortable: false,
        template: "<div>#=text#</div>",
        width: "40px"
    }, {
        field: "boo",
        hidden: true,
        sortable: true,
        template: "<div>Boo: #=text#</div>",
        width: "200px"
    }, {
        field: "baz",
        hidden: true,
        template: "baz:#=text#",
        width: "20px"
    }],
    desiredArray = [{
        field: "bar",
        hidden: false,
        sortable: false,
        template: "",
        width: "100px",
        propC: "C"
    }, {
        field: "bee",
        hidden: true,
        sortable: false,
        template: "=#text#",
        int: 4
    }, {
        field: "foo",
        hidden: true,
        sortable: false,
        template: "<div>#=text#</div>",
        width: "40px",
        propA: "a",
        propB: "b"
    }, {
        field: "baz",
        hidden: true,
        sortable: true,
        template: "<span>#=text#</span>",
        width: "20px",
        int: 3
    }],
    outputArray = [],
    pre = document.getElementById('out'),
    equalField = function (originalElement) {
        return originalElement.field === this.field;
    };

localStorageArray.reduce(function (acc, localElement) {
    var original = originalArray.find(equalField, localElement),
        shallowCopy;

    if (original) {
        shallowCopy = Object.assign({}, original);
        shallowCopy.hidden = localElement.hidden;
        shallowCopy.width = localElement.width;
        acc.push(shallowCopy);
    }

    return acc;
}, outputArray);

originalArray.forEach(function (originalElement, index) {
    if (!this.find(equalField, originalElement)) {
        this.splice(index, 0, Object.assign({}, originalElement));
    }
}, outputArray);

try {
    expect(outputArray).to.eql(desiredArray);
    pre.textContent = 'outputArray is equal to desiredArray\n\n';
} catch (e) {
    console.error(e);
    pre.textContent = 'outputArray is not equal to desiredArray\n\n';
}

pre.textContent += JSON.stringify(outputArray, null, 2);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.32.0/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.min.js"></script>
<pre id="out"></pre>
&#13;
&#13;
&#13;