객체 배열의 값에 대해 .join 수행


273

문자열 배열이 있으면 .join()메서드를 사용하여 각 요소를 쉼표로 구분하여 단일 문자열을 얻을 수 있습니다 .

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

객체 배열이 있고 그 안에 보유 된 값에 대해 유사한 작업을 수행하고 싶습니다. 그래서

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

이전과 동일한 출력을 얻으려면 속성 join에 대해서만 메소드를 수행하십시오 name.

현재 다음 기능이 있습니다.

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

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

  return out.join(", ");
}

해당 코드에는 아무런 문제가 없지만 작동하지만 갑자기 간단한 간결한 코드 줄에서 매우 필수적인 기능으로 전환했습니다. 이것을 간결하고 이상적으로 더 기능적으로 작성하는 방법이 있습니까?


1
한 언어를 예로 들어, 파이썬 방식은 이렇게합니다." ,".join([i.name for i in a])
jackweirdy

6
ES6에서는 다음을 수행 할 수 users.map(x => x.name).join(', ');있습니다..
totymedli

답변:


496

객체를 무언가 (이 경우 속성)에 매핑하려는 경우. 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(",");

(깡깡이)

ES5와 호환 되지 않는 이전 브라우저를 지원하려는 경우 이를 숨길 수 있습니다 (위의 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 프로토 타입 멤버를 shim해야합니다.
Tommi

@Tommi 좋은 의견. 밑줄을 사용할 경우 폴리 필에 대한 설명과 pluck 사용 제안을 추가했습니다.
Benjamin Gruenbaum

@ jackweirdy 나는 도움이 될 수있어서 기쁘다 :) 맵 / 축소 / 필터가 'pythonic'하지 않고 이해가 다른 방법으로 유지되는 것처럼 가치있는 것에 대해. JavaScript의 새로운 사양 진행 중 (Harmony)과 일부 브라우저 (firefox)에서는 이미 pythonic 이해력이 있습니다. [x.name for x of users](spec wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions ) 할 수 있습니다 . map / reduce / filter를 사용하는 것과 마찬가지로 JavaScript에서는 다른 방식으로 '파이 토닉'하지는 않습니다. Coffeescript는 coffeescript.org를 통해 멋지다 .
Benjamin Gruenbaum가

단지 업데이트-배열 이해가 ES6에서 제외되었습니다. 아마도 ES7에서 가져올 수 있습니다.
Benjamin Gruenbaum

coffeescript에서 :users.map((obj) -> obj.name).join(', ')
Kesha Antonov

71

글쎄 당신은 항상 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"

2
그것은 매우 흥미로운 접근법입니다. JS 에서이 작업을 수행 할 수 있다는 것을 몰랐습니다. 데이터는 API에서 제공되므로 사용 사례에 적합하지 않을 수도 있지만 확실히 생각할만한 음식입니다.
jackweirdy 11

3
너무 건조하지 않은 것
BadHorsie

3
@BadHorsie 아니요, 건조하지 않습니다. 물론 배열 외부에서 단일 함수를 정의한 다음 toStringfor 루프를 사용 하여이 함수를 모든 항목 의 메서드에 할당 할 수 있습니다 . 또는 생성자 속성을 처리 할 때 생성자 속성에 하나의 toString메서드를 추가하여이 방법을 사용할 수 있습니다 prototype. 그러나이 예제는 기본 개념을 보여주기위한 것입니다.
basilikum

13

나는 또한 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객체입니다 (의 선택적 initialValue 매개 변수 를 사용하기 때문에 reduce)

6 개월 후 편집 : 오, 내가 생각한 것. "청소기". 나는 코드 신들을 화나게했다.


고마워 : D reducemap(여러 종류의 자매라고 생각하면 이상 하다)만큼 널리 지원되지 않으므로 나는 여전히 당신의 대답을 사용하고 있습니다 :)
jackweirdy

6 개월 후 나의 편집 내용을 살펴본 결과, 나는 스스로 고용하지 않기로 결정했습니다 ... 교묘하지만 깨끗하지는 않습니다.
jackweirdy

9

외부 라이브러리를 사용하지 않고 쉽게 할 수있는 방법이 있는지 모르겠지만 개인적 으로 배열, 컬렉션 등을 처리하기위한 수많은 유틸리티가있는 underscore.js좋아 합니다 .

밑줄을 사용하면 한 줄의 코드로 쉽게 할 수 있습니다.

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


나는 전에 밑줄을 두들 겼다. 그러나 나는 네이티브 JS에서 그것을 할 수있는 방법을 바라고 있었다.-한가지 방법을 사용하기 위해 전체 라이브러리를 가져 오는 것은 약간
멍청하다.

( arr당신의 배열은 자연 스럽습니다)
Ed Hinchliffe

그럴 수 있지! 나는 지금 여기 저기 밑줄을 사용하고 있기 때문에 문제가되지 않습니다.
Ed Hinchliffe 11

5

노드 또는 ES6 +에서 :

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

3

객체 배열이 변수에 의해 참조된다고 말할 수 있습니다. users

ES6을 사용할 수 있다면 가장 쉬운 해결책은 다음과 같습니다.

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

그렇지 않은 경우 lodash를 사용할 수 있습니다.

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

2

객체 및 동적 키인 경우 : "applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}

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

0

내가 아는 낡은 실이지만 여전히이 사람을 만나는 사람에게는 매우 관련이 있습니다.

Array.map은 내가 항상 사용하는 멋진 방법 인 제안되었습니다. Array.reduce도 언급되었습니다 ...

이 유스 케이스에는 개인적으로 Array.reduce를 사용합니다. 왜? 코드가 약간 덜 깨끗하지만 명확합니다. 맵 기능을 조인에 파이프하는 것보다 훨씬 효율적입니다.

그 이유는 Array.map이 각 요소를 반복하여 배열의 객체 이름이 모두 포함 된 새 배열을 반환해야하기 때문입니다. 그런 다음 Array.join은 배열의 내용을 반복하여 결합을 수행합니다.

템플릿 리터럴을 사용하여 코드를 한 줄로 가져 오면 jackweirdys의 가독성을 향상시킬 수 있습니다. "모든 최신 브라우저에서도 지원"

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

0

확실하지 않지만,이 모든 대답은 작동하지만 두 번의 스캔을 수행하고 있기 때문에 선택적이지 않으며 단일 스캔으로 수행 할 수 있습니다. O (2n)은 O (n)으로 간주되지만 항상 진정한 O (n)를 갖는 것이 좋습니다.

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;
}

이것은 오래된 학교처럼 보이지만 다음과 같이 도둑질을 할 수 있습니다.

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

-1

이 시도

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.