【问题标题】:Programmatically modifying maps based on inner condition根据内部条件以编程方式修改地图
【发布时间】:2018-07-22 17:01:46
【问题描述】:

例如,我有一张这样的地图

const Map = new Map().set('123', [ [ 'foo', 'bar' ] ]).set('456', [ [ 'baz', 'qux' ], [ 'quux', 'corge' ] ]);
/* 
The structure of the Map looks like this:
    Map {
       '123' => [ [ 'foo', 'bar' ] ],
       '456' => [ [ 'baz', 'qux' ], [ 'quux', 'corge' ] ] 
   } 
*/

我将如何删除数组中第一个嵌套元素 === 'quux' 的数组,以便它返回这个?

Map {
    '123' => [ [ 'foo', 'bar' ] ],
    '456' => [ [ 'baz', 'qux' ] ] 
}

我知道如何删除该项目通过做

Map.set('456', (Map.get('456')).filter(array => array[0] !== 'quux'));

但这只是因为我知道哪个键 ('456') 中有包含 'quux' 的元素。我不确定如何以编程方式扫描地图,然后找到相应的键,然后删除该项目。 Map 中的键和值将是动态的(但结构将是相同的),而要搜索的元素将是静态的,即:'quux',我的意思是 Map 中的内容可能会有所不同,我只是在执行搜索和删除。

【问题讨论】:

  • 使用循环。您还应该了解forEach()map()filter()reduce() 等数组函数。
  • 你使用Map而不是一个对象有什么原因吗?
  • @Code-Apprentice 我正在使用一个使用 Maps 的库,所以我别无选择,只能使用 Map 方法来处理它。

标签: javascript dictionary ecmascript-6


【解决方案1】:

您可以迭代映射,如果找到想要的值,过滤数组并分配过滤后的数组。

const map = new Map([['123', [['foo', 'bar']]], ['456', [['baz', 'qux'], ['quux', 'corge']]]]);

map.forEach((v, k, m) => {
    if (v.some(a => a[0] === 'quux')) {
        m.set(k, v.filter(a => a[0] !== 'quux'));
    }
});

console.log([...map]);

【讨论】:

  • [...map] 的技巧很巧妙——也将它整合到我的答案中。今天学到了新东西!
【解决方案2】:

您可以遍历Map 的值,在每个值v 上使用findIndex 来查看它是否包含第一个元素为quux 的数组,如果是,则将splice 该数组取出:

const map = new Map().set('123', [ [ 'foo', 'bar' ] ]).set('456', [ [ 'baz', 'qux' ], [ 'quux', 'corge' ] ]);

console.log("before", [...map]);

for (const v of map.values()) {
  const index = v.findIndex((a) => a[0] === "quux");
  
  if (index > -1) {
    v.splice(index, 1);
  }
}

console.log("after", [...map]);

这是一个非破坏性的替代方案,它通过将旧的条目和mapping 值到filter 的值从我们不想要的数组中取出来创建一个新的 Map:

const before = new Map().set('123', [ [ 'foo', 'bar' ] ]).set('456', [ [ 'baz', 'qux' ], [ 'quux', 'corge' ] ]);

console.log("before", [...before]);

const after = new Map([...before].map(([k, v]) => {
  return [k, v.filter((a) => a[0] !== "quux")];
}))

console.log("after", [...after]);

注意:这两种方法之间的一个区别是,第二种方法将删除 allquux 作为其第一个元素的数组,而第二种方法将仅删除第一个这样的数组。当然,它们都可以进行更改以适应您需要的两个选项中的任何一个。

【讨论】:

    【解决方案3】:

    您可以像这样使用 for of 循环动态地执行密钥:

    顺便说一句,打开您的开发工具以检查新地图,因为地图无法在代码 sn-p 中正确显示。

    const Map = new Map().set('123', [
      ['foo', 'bar']
    ]).set('456', [
      ['baz', 'qux'],
      ['quux', 'corge']
    ]);
    
    
    for (let el of Map) {
      Map.set(el[0], (Map.get(el[0])).filter(array => array[0] !== 'quux'));
    }
    
    
    console.log(Map);

    我希望这是你想要的,否则你可以发表评论,我会看看它;)。

    【讨论】:

      【解决方案4】:

      遍历映射的键值对,该值将具有外部数组,我们可以从中过滤掉具有我们正在寻找的值的内部数组。我们可以从 forEach 函数中获取内部数组的索引,使用它可以使用 splice 函数从外部数组中删除内部数组。

      const map = new Map().set('123', [ [ 'foo', 'bar' ] ]).set('456', [ [ 'baz', 'qux' ], [ 'quux', 'corge' ] ]);
      map.forEach((v, k)=>
      {
           v.forEach((arr, idx)=> {
           if(arr.includes('quux')){
                  v.splice(idx,1);
              }
          },)
      });
      console.log(map);
      

      【讨论】:

        【解决方案5】:

        不确定在过滤数组之前始终使用Array.prototype.filter 或使用Array.prototype.some 是否更好。

        这个解决方案只是过滤所有数组而不检查'quux'的出现。

        const map = new Map().set('123', [ ['foo', 'bar' ] ]).set('456', [ [ 'baz', 'qux' ], [ 'quux', 'corge' ] ]);
        
        map.forEach((val, key) => {
          val = val.filter(arr => arr[0] !== 'quux');
          map.set(key, val);
        });
        
        console.log(map);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-08-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-04
          • 2015-02-27
          相关资源
          最近更新 更多