【问题标题】:dart, a nice way of replacing keys and values in maps?dart,一种替换地图中键和值的好方法?
【发布时间】:2014-03-24 13:29:50
【问题描述】:

我有一个Map,我想同时检查valueskeys,并将任何符合某些设定条件的特定对象替换为其他一些对象,所以如果我找到一个满足具体标准。
我想将该键交换为仍然指向地图中相同值对象的不同对象,类似地,如果我找到要替换的值,我希望原始键指向替换值。
这是一些适用于简化示例的代码,但它看起来很丑陋,是否有更好的方法来实现这一点,这意味着一种方法不需要您提取要替换的每个键和值,然后将替换写回在。
能够只迭代一次映射而不是迭代键,然后迭代所有要替换的键和值会更好吗?

void main(){
  //replace all values of instance A with an Object and all keys starting with "t" with the same key minus the "t"
  var m = {
    "one": new A(),
    "two": new A(),
    "three": new B(),
    "four": new B()
  };
  mapKeyAndValueSwapper(m,
    keyMeetsCondition: (k) => k.startsWith("t"),
    valueMeetsCondition: (v) => v is A,
    keyReplacer: (k) => k.replaceFirst("t", ""),
    valueReplacer: (v) => new Object());
  print(m);
}

mapKeyAndValueSwapper(Map m, {bool keyMeetsCondition(key), bool valueMeetsCondition(value), dynamic keyReplacer(key), dynamic valueReplacer(value)}){
  var keysToReplace = [];
  var keysToReplaceValuesFor = [];
  var keys = m.keys;
  keys.forEach((k){
    if(keyMeetsCondition != null){
      if(keyMeetsCondition(k)){
        keysToReplace.add(k);
      }
    }
    if(valueMeetsCondition != null){
      if(valueMeetsCondition(m[k])){
        keysToReplaceValuesFor.add(k);
      }
    }
  });
  keysToReplaceValuesFor.forEach((k){
    m[k] = valueReplacer(m[k]);
  });
  keysToReplace.forEach((k){
    m[keyReplacer(k)] = m.remove(k);
  });
}

class A{}
class B{}

【问题讨论】:

    标签: map dart


    【解决方案1】:

    您可以在 Map 上创建一个扩展,从 mapEntries 创建一个列表,然后操作该列表以更新键(使用索引来维护顺序),然​​后清除地图并从更新的列表中重建它。

    extension MapX<K, V> on Map<K, V> {
      bool updateKey({required K currentKey, required K newKey}) {
        if (containsKey(currentKey) && !containsKey(newKey)) {
          final value = this[currentKey] as V;
          final index = keys.toList().indexWhere((k) => k == currentKey);
    
          final mapEntriesList = entries.toList();
          mapEntriesList.removeAt(index);
          mapEntriesList.insert(index, MapEntry<K,V>(newKey, value));
    
          clear();
    
          addEntries(mapEntriesList);
    
          return true;
        } else {
          return false;
        }
      }
    }
    

    【讨论】:

      【解决方案2】:

      我认为这也是一样的:

        Map newMap = {};
        m.forEach((k, v) {
          var key = k;
          var value = v;
          if(m[k] is A) {
            value = new Object();
          }
          if(k.startsWith('t')) {
            key = k.replaceFirst('t', '');
          }
          newMap[key]=value;
        });
      

      【讨论】:

      • 嗯,你让我重新思考我的问题,谢谢。也许创建一个新的地图是要走的路,而不是替换现有地图中的键和值。
      • 我在映射函数中考虑了new Map.fromIterable() wher you can apply mapping but you don't have access to key`和value,但在key映射函数中只考虑了key,在value映射函数中只考虑了value
      • haivng 查看了我的代码,不幸的是,我无法使用此解决方案,因为我无权访问原始地图引用以用它将返回的新地图覆盖,我确实需要单独替换每个人现有映射中的键/值。嗯,没关系,不过对于许多其他用例来说仍然是一个不错的解决方案
      猜你喜欢
      • 1970-01-01
      • 2013-08-24
      • 1970-01-01
      • 2015-01-20
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-13
      相关资源
      最近更新 更多