1

2 つの異なる API に由来する異なる形状の 2 つのデータ構造があります。データは JSON 形式で、言語は JavaScript です。

配列 1:

[ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" },
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" }, 
                   { "html" : "some_html", "name" : "TASK_NAME_2" } ] },
  { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" },
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" }, 
                   { "html" : "some_html", "name" : "TASK_NAME_4" } ] }]

配列 2:

  [ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" }, 
      { "name" : "TASK_NAME_2", "status" : "OPEN" } ],
    [ { "name" : "TASK_NAME_3", "status" : "OPEN" }, 
      { "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ]

配列 1 のツールチップ フィールドの要素には、配列 2 の要素と同じ「名前」が含まれています。配列 2 の「ステータス」を配列 1 内のツールチップにエレガントにマージするにはどうすればよいですか?

レンズが正解かと思いましたが、使ったことがないのでわかりません。

ネストされた反復と更新配列 1 を使用して解決できるいくつかの方法を認識しています。理想的には、既存のデータ構造を変更しないアプローチを探しています。

4

3 に答える 3

1

これは少し複雑ですが、うまくいくはずです

array2.forEach(function(tooltips){
    tooltips.forEach(function(tooltip){
        for (var i = 0; i < array1.length; i++) {
            for (var j = 0; j < array1[i].tooltips.length; j++) {
                var arr1Tooltip = array1[i].tooltips[j];
                if(arr1Tooltip.name == tooltip.name)
                    arr1Tooltip.status = tooltip.status;
            };
        };        
    });
});

console.log(JSON.stringify(array1));
于 2014-07-09T11:15:58.817 に答える
0

zip.mapデータ構造がネストされているため、2 つの/が必要になりますzipWith

zip(array1, array2).map(function([obj, tooltips]) { // ES6 destructuring syntax
    return {
        document: obj.document,
        tooltips: zip(obj.tooltips, tooltips).map(function([tooltip, extender]) {
            return {
                html: tooltip.html,
                name: tooltip.name,
                status: extender.status
            };
        })
    };
})

これらのオブジェクト リテラル構造を繰り返したくない場合は、コピー機能を使用できる場合があります。例えば

extend({}, document, {tooltips:…})
extend({}, tooltip, extender);

そのためにhttps://github.com/DrBoolean/lenseshttps://github.com/fantasyland/fantasy-lensesのようなレンズ ライブラリを使用することもできますが、それが努力する価値があるかどうかはわかりません - 上記コードにはアンダースコア/ロダッシュのみが必要です。

inner を回避するには、レンズzipWithが必要になります (この記事をよく知っていると思います) が、そのような機能を提供する JavaScript ライブラリーはまだ見たことがありません。Traversal

于 2014-07-09T13:46:55.860 に答える
0

これはおそらく過度に設計されており、あまり効率的ではありませんが、再帰関数を使用してこの JSFiddleと同様に実行できます。私は疲れすぎて賢い方法でそれを行うことができません。

var arr1 = [ { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_1" },
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_1" }, 
                   { "html" : "some_html", "name" : "TASK_NAME_2" } ] },
  { "document" : { "html" : "some_html", "name" : "DOCUMENT_NAME_2" },
    "tooltips" : [ { "html" : "some_html", "name" : "TASK_NAME_3" }, 
                   { "html" : "some_html", "name" : "TASK_NAME_4" } ] }];

var arr2 = [ [ { "name" : "TASK_NAME_1", "status" : "FINISHED" }, 
      { "name" : "TASK_NAME_2", "status" : "OPEN" } ],
    [ { "name" : "TASK_NAME_3", "status" : "OPEN" }, 
      { "name" : "TASK_NAME_4", "status" : "FUTURE" } ] ];

var findStatus = function(name, searchArray) {
    var r = '';
    if (typeof searchArray === 'object') {
        if ("name" in searchArray && "status" in searchArray) {
            if (searchArray.name == name) {
                return searchArray.status;
            } else {
                return '';
            }
        } else {
            for (var i in searchArray) {
                r = findStatus(name, searchArray[i]);
                if (r != '') {
                    return r;
                }
            }
        }
    }
    return '';
};

var updateStatus = function(arrToUpdate, arrWithStatus) {
    var copy = $.extend(true, {}, arrToUpdate);
    var r = '';
    if (typeof copy === 'object') {
        if ("name" in copy) {
            r = findStatus(copy.name, arrWithStatus);
            if (r != '') {
                copy.status = r;
            }
        } else {
            for (var i in copy) {
                copy[i] = updateStatus(copy[i], arrWithStatus);
            }
        }
    }
    return copy;
};

var arr3 = updateStatus(arr1, arr2); // Final combined array

この行を追加しvar copy = $.extend(true, {}, arrToUpdate);て、ディープ コピーを実行し、元の配列を変更しないようにしました。その結果、jQuery が必要になります。

于 2014-07-09T12:49:32.630 に答える