【问题标题】:How to create a map (object) from list of strings in Javascript如何从 Javascript 中的字符串列表创建地图(对象)
【发布时间】:2014-02-27 03:30:40
【问题描述】:

我有一个包含许多唯一字符串的数组,我希望尽可能不循环,从中创建一个映射对象,其中每个元素的键是唯一字符串,值默认为任意设置.

有没有一种方法可以在一行中做到这一点而无需循环? IE。我想从

var colours = [ "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" ];

var colourMap = {
    "Red":    VAL,
    "Orange": VAL,
    "Yellow": VAL,
    "Green":  VAL,
    "Blue":   VAL,
    "Indigo": VAL,
    "Violet": VAL
};

【问题讨论】:

  • 您在下面的评论中提到您正在寻求优化此性能以提高性能,因为此代码将重复编码。首先,您不能将其缓存在更高范围的变量中吗?除非每次颜色列表或 VAL 都不同,否则没有理由不能。第二 - 你确定性能有问题吗?大多数不同的技术(for loop、reduce、forEach、underscore)具有非常相似的性能,不太可能成为您的瓶颈。微优化前的配置文件!
  • @GeorgeMauer:是的,我会跟进。我想我在这里的潜在兴趣是是否有一种方法不是 O(n) - 听起来好像没有。
  • JS 几乎不会完全遵循你在 CS 中学到的那些 ptime 预测。根据您的需要,Object.create() 可能会快很多。
  • 我认为理论上对无序数组的每个元素的任何操作都不可能小于 O(n)。但是,O(n) 不是大多数算法试图达到的确切情况吗?一旦你是 O(n),你基本上就处于“不是问题”的领域。
  • 确实如此,在 V8 或 TraceMonkey 中做一些重复性的基准测试,你就会明白我的意思了。如果例程已编译且未在运行时优化,则适用旧规则。

标签: javascript arrays string map


【解决方案1】:

如果您真的想完全跳过循环(包括像 map 这样的函数),这可行:

JSON.parse('{"'+colours.join('":"VAL", "')+'":"VAL"}');

这会构建一个 JSON 字符串,然后对其进行解析。

但是,我不会使用此功能。它丑陋,效率低下,难以维护,在“幕后”使用循环,而且它通常是不好的形式。 (我什至不会打扰eval 而不是 JSON。eval === evil)。

改用map 之类的东西:

var colours = [ "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" ];
var colourMap = {};
colours.forEach(function(c){
    colourMap[c] = "VAL";
});

是的,它循环通过colours,但它更高效,更易于理解。

关于性能:

mapreduce seem to be similar 在 Google Chrome 中的执行速度(reduce 稍快)。

【讨论】:

  • 只是一个小提示:显然它不适用于所有可能的 VALs
  • 是的,JSON 选项必须生成有效的 JSON。一些 VAL 可能会破坏它。 (这就是它是一个糟糕选择的原因之一)
  • JSON.parse 在内部使用循环,因此仍在循环。如果您真的想避免循环,您可以进行评估,但这太荒谬了。
【解决方案2】:

假设您的浏览器要求支持Array.prototype.reduce

colours.reduce(function(obj, c){ 
  obj[c] = "VAL";
  return obj;
}, {})

或者,如果你是一个混蛋并且使用大多数 js 开发人员甚至不知道存在的语法,那么你可以接受

colours.reduce(function(obj, c){ return (obj[c] = "VAL", obj) }, {})

【讨论】:

  • 语法没问题,我喜欢这个解决方案,+1!
  • @Cerbrus 一些语言称它为foldfoldlaggregate,都是同一个概念。
【解决方案3】:

你可以用 jQuery 做到这一点:

colourMap = $.map(colours, function(e){
  return { e: "VAL" };
});

或带下划线:

var colourMap = {};
_.each(some_object_array, function(val) {
  colourMap[val] = "VAL";
});

甚至更好(感谢 George Mauer):

_.object(_.map(colourMap, function(c) { return [c, "VAL"] }))

【讨论】:

  • 带下划线:_.object(_.map(colourMap, function(c) { return [c, "VAL"] })) 通常我会使用这种模式,所以我会使用_.mixin({ mapObject: _.compose(_.object, _.map) })
  • 从技术上讲,这些仍然是循环。
  • 嗯,我认为您的代码会生成一个对象数组,每种颜色一个对象。每个只有 1 把钥匙...
  • 是的,恐怕我无法访问 jQuery。务实地说,我想即使是一个班轮也可能在封面下循环。我真的在寻找最有效的方法,因为它的代码会被频繁调用。
  • 就@AndreaParodi 而言,上面的 jquery 示例不会产生您所追求的,您必须执行 colourMap = $.extend.apply($, ...) 才能将其全部放入一个对象中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-12
相关资源
最近更新 更多