在地图的特定索引处插入

时间:2018-11-10 03:25:00

标签: javascript typescript dictionary

Map的文档中说:

  

Map中的键是有序的,而添加到对象中的键则没有顺序。从而,   在其上进行迭代时,Map对象将按以下顺序返回键:   插入。

要充分利用这一点,我需要以给定的特定顺序将元素插入Map中。

我知道这可以通过数组来完成,但是我更喜欢使用Map,因为我需要通过键进行很多查找,而Map在这种情况下效果很好易于维护。

我想出了类似的方法,我想知道是否有更好的方法可以做到这一点。

  function insertAtIndex(index, key, value, map){
    var iterator1 = map[Symbol.iterator]();
    var tmpMap = new Map();
    var tmpIndex=0;
    for (let item of iterator1) {
        if(tmpIndex === index){
            tmpMap.set(key, value);
        }
        tmpMap.set(item[0], item[1]);
        tmpIndex++;
    }
    return tmpMap;
  }

  insertCardAtIndex(index: Number, key: string, value:boardCard, map:Map<string, boardCard>): Map<string, boardCard> {
    let clonedMap = new Map(map);
    let tmpMap = new Map<string, boardCard>();
    let tmpIndex = 0;

    for (let entry of Array.from(clonedMap.entries())) {
      if(tmpIndex === index){
        tmpMap.set(key, value);
      }
      tmpMap.set(entry[0], entry[1]);
      tmpIndex++;
    }

    return tmpMap;
  }

对于我的用例,我永远不必处理足以使性能成为主要问题的地图,因此,如果这样做会使代码更易读和可维护,我愿意牺牲性能。

我正在使用map的值是“字典”。无法以特定顺序插入元素的事实使我想知道,即使具有快速查找以及.has().get()和{{ 1}}确实有用,但不值得无法在特定索引处插入的麻烦。

1 个答案:

答案 0 :(得分:2)

您可以将Map转换为Array,使用Array.splice插入元素,然后再次转换为Map这不是一个有效的解决方案,但是您提到在您的用例中,可维护性比性能更重要。

如果您的索引大于地图的大小,此版本的优点是可以工作。例如,在位置map.size + 1处插入元素仍会在底部添加项目,而在您的算法中不会插入该项目。如果您确实想忽略超出范围的插入,可以通过在函数中进行检查来轻松解决该插入问题,但这似乎更可靠。

function insertAtIndex(index, key, value, map){
  const arr = Array.from(map);
  arr.splice(index, 0, [key, value]);
  return new Map(arr);
}

const m = new Map();
m.set('0', 0);
m.set('1', 1);
m.set('2', 2);

console.log(Array.from(m.keys()));

let m2 = insertAtIndex(1, '0.5', 0.5, m);
console.log(Array.from(m2));
m2 = insertAtIndex(0, '-1', -1, m2);
m2 = insertAtIndex(5, '5', 5, m2);
m2 = insertAtIndex(10, '10', 10, m2);

console.log(Array.from(m2));

请注意,类似于问题本身中的函数,上述函数会创建并返回新的Map,这意味着插入后对地图的旧引用将无效。如果您假设不变性是可以的,但是如果您的代码通常是可变的,并且您可能假定对地图的引用需要保持有效,则需要执行以下操作:

 function insertAtIndex(index, key, value, map){
  const arr = Array.from(map);
  arr.splice(index, 0, [key, value]);
  map.clear();
  arr.forEach(([k,v]) => map.set(k,v));
}

const m = new Map();
m.set('0', 0);
m.set('1', 1);
m.set('2', 2);

console.log(Array.from(m.keys()));

insertAtIndex(1, '0.5', 0.5, m);
insertAtIndex(0, '-1', -1, m);
insertAtIndex(5, '5', 5, m);
insertAtIndex(10, '10', 10, m);

console.log(Array.from(m));