Jeśli mam tablicę ciągów, mogę użyć .join()
metody, aby uzyskać pojedynczy ciąg, z każdym elementem oddzielonym przecinkami, tak jak poniżej:
["Joe", "Kevin", "Peter"].join(", ") // => "Joe, Kevin, Peter"
Mam tablicę obiektów i chciałbym wykonać podobną operację na wartości w niej zawartej; więc od
[
{name: "Joe", age: 22},
{name: "Kevin", age: 24},
{name: "Peter", age: 21}
]
wykonaj join
metodę tylko dla name
atrybutu, aby uzyskać takie same wyniki jak poprzednio.
Obecnie mam następującą funkcję:
function joinObj(a, attr){
var out = [];
for (var i = 0; i < a.length; i++){
out.push(a[i][attr]);
}
return out.join(", ");
}
Nie ma nic złego w tym kodzie, działa, ale nagle przeszedłem z prostej, zwięzłej linii kodu do bardzo wymagającej funkcji. Czy istnieje bardziej zwięzły, idealnie bardziej funkcjonalny sposób pisania tego?
javascript
arrays
object
jackweirdy
źródło
źródło
" ,".join([i.name for i in a])
users.map(x => x.name).join(', ');
.Odpowiedzi:
Jeśli chcesz mapować obiekty na coś (w tym przypadku właściwość). Myślę, że
Array.prototype.map
tego szukasz, jeśli chcesz funkcjonalnie kodować.W nowoczesnym JavaScript:
(skrzypce)
Jeśli chcesz obsługiwać starsze przeglądarki, które nie są zgodne z ES5 , możesz je przeskoczyć (na stronie MDN powyżej znajduje się wypełnienie). Inną alternatywą byłoby użycie
pluck
metody underscorejs :źródło
[x.name for x of users]
(spec wiki.ecmascript.org/doku.php?id=harmony:array_compstandingions ). Warto wspomnieć, że podobnie jak użycie mapy / zmniejszania / filtrowania nie jest zbyt „pytoniczne”, w inny sposób prawdopodobnie zachowuje się w JavaScript. CoffeeScript jest z nimi spoko, choć coffeescript.org .users.map((obj) -> obj.name).join(', ')
Zawsze możesz zastąpić
toString
metodę swoich obiektów:źródło
toString
metody wszystkich elementów za pomocą pętli for. Lub możesz użyć tego podejścia do obsługi funkcji konstruktora, dodając jednątoString
metodę doprototype
właściwości konstruktora. Ten przykład miał jednak pokazać podstawową koncepcję.Natknąłem się również na tę
reduce
metodę, tak to wygląda:(a.name || a)
Jest więc pierwszy element jest odpowiednio traktowane, reszta (gdziea
jest ciągiem znaków, i taka.name
jest nieokreślona) nie jest traktowana jak obiekt.Edycja: Teraz zmieniłem to na następujące:
który, moim zdaniem, jest czystszy, ponieważ
a
zawsze jest łańcuchem,b
zawsze jest obiektem (ze względu na użycie opcjonalnego parametru initialValue wreduce
)Edytuj 6 miesięcy później: Och, o czym myślałem. "odkurzacz". Rozgniewałem kod Bogów.
źródło
reduce
nie jest tak szeroko wspierane jakmap
(co jest dziwne, biorąc pod uwagę, że są rodzeństwem), więc wciąż używam twojej odpowiedzi :)Nie wiem, czy jest to łatwiejszy sposób bez korzystania z zewnętrznej biblioteki, ale osobiście uwielbiam underscore.js, który ma mnóstwo narzędzi do zarządzania tablicami, kolekcjami itp.
Dzięki podkreśleniu możesz to łatwo zrobić za pomocą jednego wiersza kodu:
_.pluck(arr, 'name').join(', ')
źródło
arr
oczywiście jest twoja tablica)W węźle lub ES6 +:
źródło
Powiedzmy, że zmienna odwołuje się do tablicy obiektów
users
Jeśli można użyć ES6, najłatwiejszym rozwiązaniem będzie:
Jeśli nie, można użyć lodash :
źródło
Jeśli klucze obiektowe i dynamiczne:
"applications\":{\"1\":\"Element1\",\"2\":\"Element2\"}
źródło
Stary wątek, który znam, ale nadal jest bardzo odpowiedni dla każdego, kto go napotka.
Zasugerowano tutaj Array.map, co jest niesamowitą metodą, której używam cały czas. Wspomniano także o Array.reduce ...
Osobiście użyłbym Array.reduce dla tego przypadku użycia. Czemu? Pomimo tego, że kod jest nieco mniej czysty / wyraźny. Jest to o wiele bardziej wydajne niż połączenie funkcji mapy z łączeniem.
Powodem tego jest to, że Array.map musi zapętlić każdy element, aby zwrócić nową tablicę ze wszystkimi nazwami obiektu w tablicy. Array.join następnie zapętla zawartość tablicy, aby wykonać łączenie.
Możesz poprawić czytelność jackweirdys, zmniejszając odpowiedź, używając literałów szablonów, aby wprowadzić kod do jednego wiersza. „Obsługiwane również we wszystkich nowoczesnych przeglądarkach”
źródło
nie jestem pewien, ale wszystkie te odpowiedzi działają, ale nie są optiomalne, ponieważ wykonują dwa skany i można to zrobić za jednym razem. Mimo że O (2n) jest uważane za O (n), zawsze lepiej jest mieć prawdziwe O (n).
Może to wyglądać jak stara szkoła, ale pozwala mi to robić tak:
źródło
Spróbuj tego
źródło
name
atrybut został zakodowany na stałe. (a[i].name
Nie nie używać funkcja jestname
argumentem, jest to równoważnea[i]['name']
.)