2013-05-17 60 views
154

如果我有一個字符串數組,我可以使用.join()方法得到一個單一的字符串,用逗號分隔的每個元素,像這樣:執行。加入對值

["Joe", "Kevin", "Peter"].join(", ") // => "Joe, Kevin, Peter" 

我有一個對象數組,我想對其中的值執行類似的操作;所以從

[ 
    {name: "Joe", age: 22}, 
    {name: "Kevin", age: 24}, 
    {name: "Peter", age: 21} 
] 

僅在name屬性執行join方法中,如之前以實現相同的輸出。

目前,我有以下功能:

function joinObj(a, attr){ 
    var out = []; 

    for (var i = 0; i < a.length; i++){ 
    out.push(a[i][attr]); 
    } 

    return out.join(", "); 
} 

有什麼不妥的代碼,它的工作原理是,但突然我從一個簡單的代碼,簡潔的線條去了一個非常必要的功能。有沒有更簡潔,更理想的寫作方式?

+1

要使用一種語言作爲例子,Pythonic做這件事的方式應該是'「,」。join([i.name for i in a])' – jackweirdy

+3

在ES6中,你可以這樣做:'users.map (x => x.name).join(',');'。 – totymedli

回答

288

如果你想映射對象到某些東西(在這種情況下屬性)。我認爲Array.prototype.map是你正在尋找的,如果你想在功能上編碼。

[ 
    {name: "Joe", age: 22}, 
    {name: "Kevin", age: 24}, 
    {name: "Peter", age: 21} 
].map(function(elem){ 
    return elem.name; 
}).join(","); 

在現代的JavaScript:

[ 
    {name: "Joe", age: 22}, 
    {name: "Kevin", age: 24}, 
    {name: "Peter", age: 21} 
].map(e => e.name).join(","); 

(fiddle)

如果你想支持舊的瀏覽器,不屬於ES5 complaint你能勻它(還有就是MDN頁面上的填充工具上文) 。另一種方法是使用underscorejs的pluck方法:

var users = [ 
     {name: "Joe", age: 22}, 
     {name: "Kevin", age: 24}, 
     {name: "Peter", age: 21} 
    ]; 
var result = _.pluck(users,'name').join(",") 
+1

這一個。但是,如果您需要支持這種復古瀏覽器,則需要爲IE <9的填充.map原型成員。 – Tommi

+0

@Tommi好評。我添加了關於polyfill的解釋以及如果使用下劃線使用pluck的建議。 –

+0

@jackweirdy我很高興我可以幫助:)它的價值,就像map/reduce/filter不是'pythonic',理解是另一種方式。在JavaScript的新規範(和諧)以及一些瀏覽器已經(火狐)你pythonic理解。你可以做'[x.name for x of users]'(spec http://wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions)。值得一提的是,就像使用map/reduce/filter不是'pythonic'一樣,另一種方式可能在JavaScript中存在。雖然http://coffeescript.org/與CoffeeScript很酷。 –

57

那麼你總是可以覆蓋你的對象的toString方法:

var arr = [ 
    {name: "Joe", age: 22, toString: function(){return this.name;}}, 
    {name: "Kevin", age: 24, toString: function(){return this.name;}}, 
    {name: "Peter", age: 21, toString: function(){return this.name;}} 
]; 

var result = arr.join(", "); 
//result = "Joe, Kevin, Peter" 
+1

這是一個非常有趣的方法,我沒有意識到你可以在JS中做到這一點。數據來自一個API,所以它可能不適合我的用例,但它絕對是思考的食物。 – jackweirdy

+2

看起來不太乾DRY – BadHorsie

+2

@BadHorsie不,它不幹。但是當然你可以在數組之外定義一個函數,然後使用for循環將這個函數賦值給所有項的'toString'方法。或者,在處理構造函數時,可以使用這種方法,在構造函數的'prototype'屬性中添加一個'toString'方法。然而,這個例子只是顯示了基本的概念。 – basilikum

8

我不知道是否有一個更簡單的方法來做到這一點不使用外部庫,但我個人underscore.js其中噸噸的公用事業處理陣列,收集等

與下劃線喲ü可以用一行代碼做到這一點很容易:

_.pluck(arr, 'name').join(', ')

+0

我以前曾經涉獵過下劃線,但我希望有一種方法可以在原生JS中做到 - 雖然在整個庫中使用一種方法有點愚蠢:) – jackweirdy

+0

(其中'arr'就是你的陣列,當然) –

+0

夠公平!我發現自己現在都在使用下劃線,所以這不是問題。 –

0

試試這個

var x= [ 
    {name: "Joe", age: 22}, 
    {name: "Kevin", age: 24}, 
    {name: "Peter", age: 21} 
] 

function joinObj(a, attr) { 
    var out = []; 
    for (var i=0; i<a.length; i++) { 
    out.push(a[i][attr]); 
    } 
return out.join(", "); 
} 

var z = joinObj(x,'name'); 
z > "Joe, Kevin, Peter" 
var y = joinObj(x,'age'); 
y > "22, 24, 21" 
+2

這與問題中的函數相同,除了不太靈活,因爲您已經對'name'屬性進行了硬編碼。 ('a [i] .name'不會使用你函數的'name'參數,它相當於'a [i] ['name']'。) – nnnnnn

8

我也遇到使用reduce方法,這是它的樣子:

[ 
    {name: "Joe", age: 22}, 
    {name: "Kevin", age: 24}, 
    {name: "Peter", age: 21} 
].reduce(function (a, b) {return (a.name || a) + ", " + b.name}) 

(a.name || a)是如此正確處理的第一個元素,但其餘(a是一個字符串,所以a.name未定義)不作爲對象處理。

編輯:我現在重構進一步此:

x.reduce(function(a, b) {return a + ["", ", "][+!!a.length] + b.name;}, ""); 

我相信這是因爲a清潔始終是一個字符串,b始終是一個對象(由於reduce使用optional initialValue parameter的)

6個月後編輯:哦,我在想什麼。 「清潔器」。我惹怒了密碼神。

+0

感謝:D'reduce'沒有像'map'那樣得到廣泛支持(這很奇怪,因爲他們是姐妹)所以我仍然在用你的答案:) – jackweirdy

+0

看着我6個月後的編輯,我現在決定我不會僱用自己......這很狡猾,但不乾淨。 – jackweirdy

+0

heh。您可能想要將其編輯爲答案。 –

0

在節點或ES6:

users.map(u => u.name).join(', ')

2

可以說的對象陣列被可變users

引用如果ES6可用於那麼最簡單的解決方案將是:

users.map(user => user.name).join(', '); 

如果不是,並且lodash可以這樣使用:

_.map(users, function(user) { 
    return user.name; 
}).join(', ');