2011-10-31 77 views
40

有沒有辦法從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: '' 
} 
+0

有許多實現用於jQuery的'.serializeObject':https://raw.github.com/cowboy/jquery-misc/master/jquery.ba-serializeobject.js –

回答

22

都能跟得上。理解僅在CoffeeScript中返回數組。在問題跟蹤器中搜索object comprehensions,您會發現幾個提議,但沒有一個適合您。

+18

可惜,對象理解或者至少是某種功能對象構造函數應該是核心的一部分。 – tokland

+3

我回到這個帖子發現我已經投票了。我不能相信這被忽略,這是非常有用的。 – David

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' 
+0

已過期+1!這非常聰明! – slezica

+0

確實很聰明。謝謝 – Tobia

+9

聰明,但完全無法理解。有什麼辦法讓下一代更具可讀性? – relet

7

檢查功能庫underscore從這個mixin擴展_.mash

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

我相信你可以就在CoffeeScript中沒有添加的庫做到這一點。

它應該是對的效果:

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

這裏是罐裝的例子更長的響應:

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

您可以通過創建前的form_values簡化的語法:

舉一個非常簡單的例子,您想將obj映射到名稱值:

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

[{名: 'A',值:1}, {名稱: 'B',值:2}, {名稱: 'C',值: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:{鍵: 'ABC',所以meVar:1}, DEF:{鍵: 'DEF',someVar:2}}

在上述碼x以前未在範圍所限定,因此,使用=>@允許我們結合x與如果以前未找到,則設置密鑰@x || @x = {}

如果你不想用=>和@你必須事先定義X:

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

{ABC:{關鍵: 'ABC',someVar:1}, 高清: {鍵:「高清」,someVar:2}}

3

這已經回答了,但可能缺乏一些解釋,因爲這成語是相當神祕一見鍾情:

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)與一個匿名構造函數(-> ...),將創建各種字段。

2

的CoffeeScript的創建者suggests using a helper function到對數組轉換成一個對象:

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

這無疑是做的,當前語言語法中的最易讀的方式。這與Python和其他語言如何操作非常相似,除了缺少語法糖。

助手功能可以很容易地編寫一次,使用例如由@ matyr的技術和@維爾託德的答案:

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

使用underscore's object function,你可以這樣做:

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

這在過去對我來說非常合適。 – Crisfole

+0

「_.object」是新的,或者我完全錯過了它。 – tokland

+0

如果您正在使用[lodash](https://lodash.com/),請改用['fromPairs'](https://lodash.com/docs#fromPairs)函數。 – reubano