37297


JavaScriptの配列について教えてください。

[code]

    itemsA = [{id:"1"},{name:"a"},{flg:""},
                {id:"2"},{name:"b"},{flg:""},
                {id:"3"},{name:"c"},{flg:""}];
    
    itemsB = [{name:"b"},
                {name:"b"},
                {name:"c"}];
    
[/code]

上記のような２つの配列から、以下の配列を作成したいです。  
( itemsAとitemsBの配列で、同じ「name」があるデータのみ、「flg:"1"」としたいです )

[code]

    results = [{id:"1"},{name:"a"},{flg:""},
                {id:"2"},{name:"b"},{flg:"1"},
                {id:"3"},{name:"c"},{flg:"1"}];
    
[/code]

色々試しましたが、うまくいきませんでした。  
ご教授の程、よろしくお願い致します。


CC BY-SA 3.0
2017-08-17T02:29:33.763
37262
2017-08-18T12:23:25.933
19657
question
javascript
JavaScriptの配列について


# 元々の構造を維持した場合

オブジェクトの構造で疑問に思う部分は多々ありますが、元の構造を尊重するなら `{name:"***"}` が存在する index が「 **1 + 3 *
N** 」で表せる事に注目して下さい。

[code]

    'use strict';
    function generateItems1 (itemsA, itemsB) {
      const keys = new Set(itemsB.map(object => object.name));
      const items = itemsA.slice();
    
      for (let i = 1, len = items.length; i < len; i += 3) {
    if (keys.has(items[i].name)) {
      items[i + 1].flg = '1';
    }
      }
    
      return items;
    }
    
    const itemsA = [{id:"1"},{name:"a"},{flg:""},{id:"2"},{name:"b"},{flg:""},{id:"3"},{name:"c"},{flg:""}];
    const itemsB = [{name:"b"},{name:"b"},{name:"c"}];
    const items = generateItems1(itemsA, itemsB);
    
    console.log(JSON.stringify(items)); // [{"id":"1"},{"name":"a"},{"flg":""},{"id":"2"},{"name":"b"},{"flg":"1"},{"id":"3"},{"name":"c"},{"flg":"1"}]
    console.log(JSON.stringify([{id:"1"},{name:"a"},{flg:""},{id:"2"},{name:"b"},{flg:"1"},{id:"3"},{name:"c"},{flg:"1"}]) === JSON.stringify(items));  // true
[/code]

# 構造を変更した場合 (配列版)

letrec さんが指摘されたように、構造を変更した場合のコードです。

[code]

    'use strict';
    function generateItems2 (itemsA, itemsB) {
      const keys = new Set(itemsB.map(object => object.name));
      const items = [];
    
      for (let i = 0, len = itemsA.length; i < len; i += 3) {
        const item = Object.assign({}, itemsA[i], itemsA[i + 1], itemsA[i + 2]);
    
        if (keys.has(item.name)) {
          item.flg = '1';
        }
    
        items.push(item);
      }
    
      return items;
    }
    
    const itemsA = [{id:"1"},{name:"a"},{flg:""},{id:"2"},{name:"b"},{flg:""},{id:"3"},{name:"c"},{flg:""}];
    const itemsB = [{name:"b"},{name:"b"},{name:"c"}];
    const items = generateItems2(itemsA, itemsB);
    
    console.log(JSON.stringify(items));  // [{"id":"1","name":"a","flg":""},{"id":"2","name":"b","flg":"1"},{"id":"3","name":"c","flg":"1"}]
[/code]

# 構造を変更した場合 (Map版)

ユニークな id を key にした Map オブジェクトを作ります。

[code]

    'use strict';
    function generateItems3 (itemsA, itemsB) {
      const keys = new Set(itemsB.map(object => object.name));
      const items = new Map;
    
      for (let i = 0, len = itemsA.length; i < len; i += 3) {
        const item = Object.assign({}, itemsA[i], itemsA[i + 1], itemsA[i + 2]);
    
        if (keys.has(item.name)) {
          item.flg = '1';
        }
    
        items.set(item.id, item);
      }
    
      return items;
    }
    
    const itemsA = [{id:"1"},{name:"a"},{flg:""},{id:"2"},{name:"b"},{flg:""},{id:"3"},{name:"c"},{flg:""}];
    const itemsB = [{name:"b"},{name:"b"},{name:"c"}];
    const items = generateItems3(itemsA, itemsB);
    
    console.log(JSON.stringify([...items.entries()]));  // [["1",{"id":"1","name":"a","flg":""}],["2",{"id":"2","name":"b","flg":"1"}],["3",{"id":"3","name":"c","flg":"1"}]]
    
    const item1 = items.get('1'); // id = "1" のオブジェクトを得る
    console.log(item1);  // {id: "1", name: "a", flg: ""}
[/code]

Re: Taka M さん


CC BY-SA 3.0
2017-08-17T11:54:02.693
37286
2017-08-18T12:23:25.933
2017-08-18T12:23:25.933
20262
20262
37262
answer


検索条件の `itemsB` は検索に向いたデータ構造ではないので、検索用のオブジェクト `inB` に最初に詰め替えます。

[code]

    itemsA = [{id:"1"},{name:"a"},{flg:""},
            {id:"2"},{name:"b"},{flg:""},
            {id:"3"},{name:"c"},{flg:""}];
    itemsB = [{name:"b"},
            {name:"b"},
            {name:"c"}];
    results = [];
    
    // 検索用オブジェクトに詰め替え:
    let inB = {};
    itemsB.forEach(function(b) {
        inB[b.name] = !!b.name;
    });
    
    for (let i = 0; i < itemsA.length; i += 3) {
      let id = itemsA[i].id, name = itemsA[i + 1].name, flg = itemsA[i + 2].flg;
    
      // itemsB に name があれば、flg = "1"
      inB[name] && (flg = "1");
    
      results.push({id: id}, {name: name}, {flg: flg});
    }
    
    console.log(results);
[/code]

また質問の前提条件にある `itemsA` ですが、配列内で連続している `id, name, flg` が一対一の関係にあるデータ構造でしょうか。  
一対一の関係をもったデータは、letrec さんのコメントにもあったように `{id: "1", name: "a", flg: ""}`
とする方が、より自明な良いデータ構造になります。

もしデータ構造を変更する場合は、上記コードの for 文を変更してください。

[code]

    for (let i = 0; i < itemsA.length; i++) {
        let id = itemsA[i].id, name = itemsA[i].name, flg = itemsA[i].flg;
    
        // itemsB に name があれば、flg = "1"
        inB[name] && (flg = "1");
    
        results.push({id: id, name: name, flg: flg});
    }
    
[/code]


CC BY-SA 3.0
2017-08-18T03:36:28.817
37297
2017-08-18T03:36:28.817
8431
37262
answer