CoffeeScript中的理解对象[dict / hash comprehensions]

时间:2011-10-31 02:52:44

标签: coffeescript

有没有办法从coffeescript的理解中返回一个对象?这样我可以表达这个:

form_values = () ->
  ret = {}
  ret[f.name] = f.value for f in $('input, textarea, select')
  return ret
像这样:

form_values = () -> f.name, f.value for f in $('input, textarea, select')

我想构建一个单个对象(不是一个对象数组)。所以如果标记看起来像这样:

<form name=blah>
  <input type=text name=blah1 value=111 />
  <textarea name=blah2>222</textarea>
  <select name=blah3>
    <option value=333a>
    <option value=333b>
  </select>
</form>

返回的对象将是这样的:

{
  blah1: '111',
  blah2: '222',
  blah3: ''
}

8 个答案:

答案 0 :(得分:26)

form_values = new ->
  @[f.name] = f.value for f in $ 'input, textarea, select'
  this

form_values = new class then constructor: ->
  @[f.name] = f.value for f in $ 'input, textarea, select'

答案 1 :(得分:22)

不。理解只返回CoffeeScript中的数组。在问题跟踪器中搜索object comprehensions,您会找到几个提案,但没有找到合适的提案。

答案 2 :(得分:7)

underscore检查功能库mixin和扩展程序_.mash

form_values = ->
  _($('input, textarea, select')).mash f -> [f.name, f.value]

答案 3 :(得分:6)

使用underscore's object function,您可以执行此操作:

form_values = _.object([f.name, f.value] for f in $('input, textarea, select'))

答案 4 :(得分:4)

这已经得到了回答,但可能缺乏一些解释,因为这个成语一见钟情神秘

form_values = (new -> @[f.name] = f.value for f in $ 'input, textarea, select'; @)
//             ^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  ^  
//           create                      with                                   |
//           a new                       that                                   |
//           empty                     anonymous                                |
//           object                   constructor                               |
//                                                                don't forget -/
//                                                                to return the
//                                                             newly created object

关键的想法是创建一个空对象(new),其中包含一个匿名构造函数(-> ...),它将创建各种字段。

答案 5 :(得分:3)

CoffeeScript的创建者suggests using a helper function将对数组转换为对象:

form_values = toObject([f.name, f.value] for f in $('input, textarea, select'))

在当前的语言语法中,这可以说是最易读的方式。除了缺少语法糖之外,它与Python和其他语言的表现方式非常相似。

帮助函数可以很容易地编写一次,例如使用来自@ matyr&s和@ Sylvain的答案的技术:

// Create a new object from an array of [key, value] pairs.
toObject = (pairs) ->
    new -> @[key] = value for [key, value] in pairs; @

答案 6 :(得分:2)

我相信你可以在CoffeeScript中没有添加库。

这应该是:

的效果
$('input, textarea, select').each (item) => @form_values || @form_values = {}; @form_values[$(item).name] = $(item).value

您可以通过预创建form_values来简化其语法:

form_values = {}
$('input, textarea, select').each (item) -> form_values[$(item).name] = $(item).value

这是一个较长的响应,包含了示例:

举一个非常简单的例子,你想把obj映射到名字值:

items = [ { a: 1 }, { b: 2 }, { c: 3 } ]
items.map((item) -> {name: Object.keys(item)[0], value: item[Object.keys(item)[0]]})
  

[{name:'a',value:1},     {name:'b',value:2},     {name:'c',value:3}]

请注意,上面并不是对象理解,只是演示了一个例子。

现在假设有更多结构,你只想映射一个已知的唯一键:

items = [{key: "abc", someVar: 1}, {key: "def", someVar: 2}]

在Python中,您可以执行以下简单操作:{x['key']:x for x in items}

在CoffeeScript中,您可以将所有这些内容归结为一行,但需要注意:

items.forEach (item) => @x || @x = {}; @x[item['key']] = item
  

{abc:{key:'abc',someVar:1},     def:{key:'def',someVar:2}}

在上面的代码中,x先前未在范围内定义,因此使用=>@允许我们将x@x || @x = {}绑定(如果之前未找到),然后设置密钥。

如果您不想使用=&gt;和@你必须事先定义x:

x = {}
items.forEach (item) => x || x = {}; x[item['key']] = item
  

{abc:{key:'abc',someVar:1},     def:{key:'def',someVar:2}}

答案 7 :(得分:0)

不要打败死马,但我个人认为这是可读的并且满足'一线'要求而无需额外的模块:

form_values = {}; form_values[f.name] = f.value for f in $('input, textarea, select')

不要忘记你仍然可以使用分号来组合Coffeescript中的行!