Umiarkowanie proste ćwiczenie, piszemy w JavaScript funkcję array_column (znaną z języka PHP) na 4 różne sposoby:
- w klasycznej pętli
- używając map
- korzystając z reduce
- korzystając z Array.from
W języku PHP mamy taką funkcję, jak array_column. Przydaje się ona do wyciągania wartości, gdy mamy do czynienia z listą obiektów, a chcemy dostać listę tylko określonej wartości. Czyli – mamy listę obiektów typu uczeń, każdy uczeń ma swoją ocenę, chcemy dostać listę ocen.
Postaramy się osiągnąć podobną funkcjonalność w JavaScript, na różne sposoby, posługując się poniższym przykładem:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Welcome to my website</h1>
<script>
const students = [
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
];
</script>
</body>
</html>
Sposób 1 – pętla
Sposób pierwszy, czyli utworzenie nowej tablicy 'grades’, przejście w pętli po 'students’ i dodanie do grades każdej oceny. Przechodzić w pętli po tablicy możemy na różne sposoby (choćby klasyczny for, for…of, for…in), my sobie użyjemy pętli forEach:
<script>
const students = [
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
];
let grades = [];
students.forEach((student)=> {
grades.push(student.grade)
});
console.log(grades);
//[5, 6, 4]
</script>
Jak widać, forEach przechodzi po każdym elemencie students i dodaje jego ocenę do tablicy grades. Mamy wynik. Oczywiście pętla może być dowolna, na upartego nawet pętli while moglibyśmy użyć.
Sposób 2 – reduce
Jest to drugi, trudniejszy sposób. Użyjemy sobie reduce z pustą tablicą jako akumulatorem.
<script>
const students = [
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
];
let grades = students.reduce((acc, student) => {
acc.push(student.grade);
return acc;
}, []);
console.log(grades);
//[5, 6, 4]
</script>
Pusta tablica jako akumulator. Funkcja przekazana do reduce musi przyjmować argumenty akumulator i aktualny element i zwracać akumulator – i to właśnie robi.
Przechodząc po tablicy students reduce do – początkowo pustej tablicy – ładuje ocenę każdego elementu i tym samym zwraca tablicę elementów grade.
Jeżeli ten sposób nam się nie podoba – słusznie, jest mało intuicyjny. Oto nowy, lepszy sposób:
Sposób 3 – funkcja map
Ten sposób jest tak banalny, że aż muszę go pokazać. Ale najpierw małe przypomnienie, jak działa map:
const array1 = [1, 4, 9, 16];
const map1 = array1.map((x) => x * 2);
console.log(map1);
// Expected output: Array [2, 8, 18, 32]
Jeżeli nie chcemy główkować samemu, oto sposób na wyciągnięcie kolumny używając map:
<script>
const students = [
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
];
let grades = students.map((student) => student.grade);
console.log(grades);
//[5, 6, 4]
</script>
Funkcja przekazana do map przechodzi po każdym elemencie i „obrabia” go w sposób, jaki sobie zażyczymy, zwracając nową tablicę.
Tutaj sobie zażyczyliśmy, aby zamiast obiektu, zwrócić jego ocenę – i dostaliśmy listę ocen.
Sposób 4 – Array.from
Wprowadźmy pewne utrudnienie – teraz students nie będzie listą, ale zbiorem (Set).
<script>
const students = new Set([
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
]);
</script>
Wiemy, że Array.from jest w stanie zamienić obiekt listo-podobny do listy, zaś map wykonać to, czego chcemy.
<script>
const students = new Set([
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
]);
const studentsArr = Array.from(students);
const grades = studentsArr.map((student) => student.grade);
console.log(grades);
//[5, 6, 4]
</script>
Ale czy wiedzieliśmy, że Array.from może to zrobić za jednym razem? Jako opcjonalny, drugi argument, możemy podać funkcję, zaś Array.from zamieni nam coś tablicopodobnego na tablicę i wykona na nim map, według naszej funkcji:
<script>
const students = new Set([
{
name: "John",
grade: 5
},
{
name: "Jane",
grade: 6
},
{
name: "Bob",
grade: 4
}
]);
const grades = Array.from(students, (student) => student.grade);
console.log(grades);
//[5, 6, 4]
</script>