2013-09-26 146 views
103

underscore.js中的map函數(如果使用JavaScript對象調用)返回從對象值中映射的值數組。對象保留鍵映射

_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; }); 
=> [3, 6, 9] 

有沒有辦法讓它保存密鑰?即,我想要一個函數返回

{one: 3, two: 6, three: 9} 
+0

如果你和我一樣,來這裏尋找改變實際的對象,而不是返回一個新的「mapValues」之類的函數,看看這個簡單的解決方案了:HTTP://計算器。 com/questions/30894044 /破壞性地圖 - 對象 - 屬性 - 函數 –

回答

178

隨着下劃線

下劃線提供了一個函數_.mapObject映射值和保留的密鑰。

_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; }); 

// => { one: 3, two: 6, three: 9 } 

DEMO


隨着Lodash

Lodash提供了一個函數_.mapValues映射值和保留的密鑰。

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; }); 

// => { one: 3, two: 6, three: 9 } 

DEMO

+0

謝謝!我看到了這樣的功能和想法,但我想知道是否有更直接的方法來映射對象。 – xuanji

+0

已經有努力獲得_。mapValues函數變成下劃線:[相關問題](https://github.com/jashkenas/underscore/issues/220),[拉取_.mapValues請求](https://github.com/jashkenas/underscore/pull/) 1953年)。我希望這能通過:) – raffomania

+0

它在我看來像是在將一個對象變成一個對象,還是我不在意? – jsh

3

_.map返回一個數組,而不是一個對象。

如果你想要一個對象,你最好使用不同的功能,如each;如果你真的想使用的地圖,你可以做這樣的事情:

Object.keys(object).map(function(value, index) { 
    object[value] *= 3; 
}) 

但是這是混亂的,眼看map人會期望有一個數組作爲結果,然後使一些用它的時候。

+0

我有一種閱讀文檔的感覺,認爲嘗試不太自然這在underscore.js中。我認爲我的用例很自然,他們爲什麼不支持它? – xuanji

+0

其中一個原因可能是'map'用於更改輸出以生成數組作爲輸出,您可以將__object和__map作爲@GG來組合。寫道,但這是一個在這一點上的品味問題。 –

2

我想你想一個mapValues功能(映射在對象的值的函數),這是很容易的實現自己:

mapValues = function(obj, f) { 
    var k, result, v; 
    result = {}; 
    for (k in obj) { 
    v = obj[k]; 
    result[k] = f(v); 
    } 
    return result; 
}; 
52

我設法在lodash中找到所需的函數,這是一個類似於下劃線的實用程序庫。

http://lodash.com/docs#mapValues

_.mapValues(object, [callback=identity], [thisArg]) 

創建具有由 運行的每個擁有通過回調對象的可枚舉屬性所產生的相同的密鑰對象和值的對象。 回調被綁定到thisArg並用三個參數調用; (值,鍵,對象)。

17

var mapped = _.reduce({ one: 1, two: 2, three: 3 }, function(obj, val, key) { 
 
    obj[key] = val*3; 
 
    return obj; 
 
}, {}); 
 

 
console.log(mapped);
<script src="http://underscorejs.org/underscore-min.js"></script> 
 
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

1

爲下劃線地圖錯誤混合修復:P

_.mixin({ 
    mapobj : function(obj, iteratee, context) { 
     if (obj == null) return []; 
     iteratee = _.iteratee(iteratee, context); 
     var keys = obj.length !== +obj.length && _.keys(obj), 
      length = (keys || obj).length, 
      results = {}, 
      currentKey; 
     for (var index = 0; index < length; index++) { 
      currentKey = keys ? keys[index] : index; 
      results[currentKey] = iteratee(obj[currentKey], currentKey, obj); 
     } 
     if (_.isObject(obj)) { 
      return _.object(results) ; 
     } 
     return results; 
    } 
}); 

簡單的解決方法,保持正確的鍵和返回爲目標 它仍然使用與我客人相同的方式,您可以使用此功能 覆蓋bugy _.map功能

或簡稱爲我用它作爲一個混合

_.mapobj (options , function(val, key, list) 
13

我知道這是舊的,但現在有下劃線爲對象的新地圖:

_.mapObject(object, iteratee, [context]) 

你當然也可以建立兩個陣列靈活的地圖和對象

_.fmap = function(arrayOrObject, fn, context){ 
    if(this.isArray(arrayOrObject)) 
     return _.map(arrayOrObject, fn, context); 
    else 
     return _.mapObject(arrayOrObject, fn, context); 
} 
+4

請注意lodash用戶:jdalton已決定[與underscore.js兼容](https://github.com/lodash/lodash/issues/980)對此進行修改。 lodash不會支持'mapObject';相反,請查看lodash的'mapValues'方法。 –

7

如何ABO用普通JS(ES6/ES2015)這個版本?

let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3}))); 

jsbin

如果你想一個對象遞歸(映射嵌套OBJ),它可以這樣做映射過來:

const mapObjRecursive = (obj) => { 
    Object.keys(obj).forEach(key => { 
    if (typeof obj[key] === 'object') obj[key] = mapObjRecursive(obj[key]); 
    else obj[key] = obj[key] * 3; 
    }); 
    return obj; 
}; 

jsbin

由於ES7/ES2016您可以使用Object.entries而不是Object.keys這樣的:

let newObj = Object.assign(...Object.entries(obj).map([k, v] => ({[k]: v * 3}))); 
0

我知道這是一個很長的時間,但仍可通過倍最明顯的解決方案(又名在JS減少)丟失,爲了完整起見,我會離開這裏:

function mapO(f, o) { 
    return Object.keys(o).reduce((acc, key) => { 
    acc[key] = f(o[key]) 
    return acc 
    }, {}) 
}