Nesneler dizisinde .join on değerini gerçekleştirme


273

Dizeleri bir dizi varsa .join(), her öğe virgülle ayrılmış olarak tek bir dize almak için yöntemi kullanabilirsiniz, böylece:

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

Nesnelerin bir dizi var ve ben içinde tutulan bir değer üzerinde benzer bir işlem gerçekleştirmek istiyorum; bu yüzden

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

daha önce olduğu gibi aynı çıktıyı elde etmek için joinyöntemi yalnızca nameöznitelik üzerinde gerçekleştirin .

Şu anda aşağıdaki işlevi var:

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

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

  return out.join(", ");
}

Bu kodla ilgili yanlış bir şey yok, işe yarıyor, ama birdenbire basit, özlü bir kod satırından çok zorunlu bir işleve gittim. Bunu yazmanın daha özlü, ideal olarak daha işlevsel bir yolu var mı?


1
Bir dili örnek olarak kullanmak için, bunu yapmanın Pythonic yolu şöyle olacaktır" ,".join([i.name for i in a])
jackweirdy

6
ES6 size yapabilirsiniz: users.map(x => x.name).join(', ');.
totymedli

Yanıtlar:


496

Nesneleri bir şeyle eşleştirmek istiyorsanız (bu durumda bir özellik). Array.prototype.mapFonksiyonel olarak kodlamak istiyorsanız aradığınız şey sanırım .

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

Modern JavaScript'te:

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

(Vaktini boşa harcamak)

Daha eski tarayıcıları desteklemek istiyorsanız, ES5 uyumlu olmayanlar onu taklit edebilirsiniz (yukarıdaki MDN sayfasında bir çoklu dolgu vardır). Başka bir alternatif, underscorejs pluckyöntemini kullanmak olacaktır :

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

1
Bu. Ancak, bu retro tarayıcıları desteklemeniz gerekiyorsa IE <9 için .map prototip üyesini ayarlamanız gerekir.
Tommi

@Tommi iyi yorum. Bir poli dolgu hakkında bir açıklama ve alt çizgi kullanıyorsanız pluck kullanmak için bir öneri ekledim.
Benjamin Gruenbaum

@jackweirdy Ben yardımcı olabilirim sevindim :) değer için ne, tıpkı harita / azaltmak / filtre 'pitonik' değildir ve anlayış diğer yolu tutar. JavaScript'in devam eden yeni spesifikasyonunda (Harmony) ve bazı tarayıcılarda (firefox) pitonik kavrayışlarınız var. Yapabilirsiniz [x.name for x of users](spec wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions ). Harita / indirgeme / filtre kullanma gibi çok 'pythonic' gibi büyük olasılıkla JavaScript'te tutar. CoffeeScript, coffeescript.org olsa da onlarla harika .
Benjamin Gruenbaum

ES6'dan sadece bir güncelleme - dizi kavrayışı bırakıldı, belki de bunları ES7'de elde ederiz.
Benjamin Gruenbaum

Kahve dilinde:users.map((obj) -> obj.name).join(', ')
Kesha Antonov

71

Peki her zaman toStringnesnelerinizin yöntemini geçersiz kılabilirsiniz :

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"

2
Bu oldukça ilginç bir yaklaşım, bunu JS'de yapabileceğinizin farkında değildim. Veriler bir API'den geliyor, bu yüzden muhtemelen benim kullanım durumum için uygun değil, ama kesinlikle düşünce için yiyecek.
jackweirdy

4
Çok KURU görünmüyor
BadHorsie

3
@BadHorsie Hayır, KURU değil. Ancak elbette, dizinin dışında tek bir işlev tanımlayabilir ve sonra bu işlevi toStringbir for-loop kullanarak tüm öğelerin yöntemine atayabilirsiniz . Veya yapıcı işlevleriyle uğraşırken, yapıcı özelliğine bir toStringyöntem ekleyerek bu yaklaşımı kullanabilirsiniz prototype. Ancak bu örneğin sadece temel konsepti göstermesi gerekiyordu.
basilikum

13

Ben de reduceyöntemi kullanarak karşılaştım , bu böyle görünüyor:

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

Bu (a.name || a)nedenle, ilk öğeye doğru davranılır, ancak geri kalanı (burada abir dize ve a.nametanımsızdır) nesne olarak değerlendirilmez.

Düzenleme: Şimdi bu daha da refactored ettik:

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

aher zaman bir dize olduğu gibi daha temiz olduğuna inanıyorum, her bzaman bir nesnedir ( isteğe bağlı initialValue parametresinin kullanılması nedeniyle reduce)

6 ay sonra düzenleyin: Ah ne düşünüyordum. "Temizleyici". Tanrıların kodunu kızdırdım.


Teşekkür: D reduceolarak yaygın olarak desteklenmez map(garip olan kız onlar meyilli biriyseniz verilen) Hala cevap :) kullanıyorum böylece
jackweirdy

6 ay sonra düzenlememe baktığımda, şimdi kendimi işe almayacağım karar verdim ... Bu kurnaz, ama temiz değil.
jackweirdy

9

Harici bir kütüphane kullanmadan bunu yapmak için daha kolay bir yol varsa bilmiyorum, ama ben şahsen seviyorum underscore.js diziler, koleksiyonlar vb başa çıkmak için yardımcı programlar ton vardır

Alt çizgi ile bunu bir kod satırı ile kolayca yapabilirsiniz:

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


Ben daha önce alt çizgi dabbled, ben yerel JS yapmak için bir yol olsa umuyordum - bir kez bir yöntem kullanmak için bütün bir kütüphane çekmek için biraz daft :)
jackweirdy

( arrdoğal olarak diziniz nerede )
Ed Hinchliffe

yeterince adil! Kendimi şimdi her yerde alt çizgi kullanarak bulmak, bu yüzden bir sorun değil.
Ed Hinchliffe

5

Düğümde veya ES6 + 'da:

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

3

diyelim ki nesneler dizisine değişken tarafından başvuruluyor users

ES6 kullanılabiliyorsa, en kolay çözüm:

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

Değilse ve lodash şu şekilde kullanılabilir:

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

2

Nesne ve dinamik anahtarlar ise: "applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}

Object.keys(myObject).map(function (key, index) {
    return myObject[key]
}).join(', ')

0

Eski bir iş parçacığı biliyorum ama yine de süper gelen herkes bu rastlamak.

Burada her zaman kullandığım harika bir yöntem olan Array.map önerildi. Array.reduce da bahsedildi ...

Şahsen bu kullanım durumu için bir Array.reduce kullanırdım. Neden? Kod biraz daha az temiz / açık olmasına rağmen. Harita işlevini bir birleştirmeye bağlamaktan çok daha verimlidir.

Bunun nedeni, Array.map'nin dizideki nesnenin tüm adlarını içeren yeni bir dizi döndürmek için her öğenin üzerinde döngü yapması gerektiğidir. Array.join daha sonra birleştirme işlemini gerçekleştirmek için dizi içeriğinin üzerine döner.

Kodu tek bir satıra almak için şablon değişmezlerini kullanarak jackweirdys azaltma yanıtının okunabilirliğini artırabilirsiniz. "Tüm modern tarayıcılarda da desteklenir"

// a one line answer to this question using modern JavaScript
x.reduce((a, b) => `${a.name || a}, ${b.name}`);

0

emin değilim, ancak tüm bu cevaplar işe yarıyor ama iki tarama yapıyorlar ve optiomal değiller ve bunu tek bir taramada yapabilirsiniz. O (2n) O (n) olarak kabul edilmesine rağmen, gerçek bir O (n) 'ye sahip olmak her zaman daha iyidir.

const Join = (arr, separator, prop) => {
    let combined = '';
    for (var i = 0; i < arr.length; i++) {
        combined = `${combined}${arr[i][prop]}`;
        if (i + 1 < arr.length)
            combined = `${combined}${separator} `;
    }
    return combined;
}

Bu eski okul gibi görünebilir, ancak böyle bir şey yapmama izin veriyor:

skuCombined = Join(option.SKUs, ',', 'SkuNum');

-1

bunu dene

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
Bu, söz konusu işlevle aynıdır, ancak özelliği çok az kodladığınız için daha az çok yönlüdür name. ( a[i].nameYok değil senin işlevin kullanmak nameargüman, bu eşdeğerdir a[i]['name'].)
nnnnnn
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.