Domů O mně Služby Portfolio Učím Blog Kontakt
← Zpět na učím

04.06 Filter

Výuka

Proč Filter?

filter() je metoda, která filtruje prvky pole podle podmínky a vytvoří nové pole jen s prvky, které podmínku splnily.

Proč to potřebujeme?

  • Výběr dat - Vyber jen prvky, které splňují kritérium (sudá čísla, aktivní uživatelé)
  • Filtrování - Odstraň nechtěné prvky (null hodnoty, duplicity)
  • Immutability - Vytvoř nové pole, nezměň originál (bezpečné pro React state)
  • Čitelnost - Místo smyčky s podmínkou použiješ deklarativní filtr

Představ si to jako: Cedník na těstoviny. Dáš dovnitř směs těstovin a vody, cedník propustí jen těstoviny (splňují podmínku "je pevné"). Voda (nesplňuje) odteče pryč.

Jak to funguje?

1. filter(fn) - zavolá funkci fn pro každý prvek pole
2. Funkce fn vrací true (prvek projde) nebo false (prvek se zahodí)
3. Vytvoří NOVÉ pole jen s prvky, kde fn vrátila true
4. NEMĚNÍ původní pole (immutabilní)
5. Výsledné pole může být KRATŠÍ než originál (nebo i prázdné)

Klíčové koncepty

  • filter(predicate) - filtruje prvky podle podmínky, vrací nové pole
  • Predicate - funkce vracející true nebo false: (element, index, array) => boolean
  • Immutability - filter() NEMĚNÍ originál
  • Nový počet prvků - výsledek může mít méně prvků (nebo 0)
  • Pure function - predikát by neměl mít vedlejší efekty
  • Chainable - můžeš řetězit: arr.filter(...).map(...)

JavaScript

Příklad 1: Základní filtrování - sudá čísla

const numbers = [1, 2, 3, 4, 5, 6];

const even = numbers.filter(function(num) {
  return num % 2 === 0;
});

console.log(even);
// → [2, 4, 6]

console.log(numbers);
// → [1, 2, 3, 4, 5, 6] (originál NEZMĚNĚN)

Co se stalo?

  • filter() zavolá funkci pro každý prvek
  • Funkce vrací true pro sudá čísla (num % 2 === 0)
  • Pouze prvky, kde funkce vrátila true, se dostanou do nového pole
  • Původní pole zůstává netknuté

Příklad 2: Arrow funkce (kratší syntax)

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Sudá čísla
const even = numbers.filter(n => n % 2 === 0);
console.log(even);
// → [2, 4, 6, 8, 10]

// Čísla větší než 5
const greaterThan5 = numbers.filter(n => n > 5);
console.log(greaterThan5);
// → [6, 7, 8, 9, 10]

// Násobky 3
const multiplesOf3 = numbers.filter(n => n % 3 === 0);
console.log(multiplesOf3);
// → [3, 6, 9]

Co se stalo?

  • n => n % 2 === 0 je arrow funkce s implicitním return
  • Stručnější a čitelnější
  • Každý filter vytvoří nové pole

Příklad 3: Filtrování objektů

const users = [
  { name: 'Alice', age: 25, active: true },
  { name: 'Bob', age: 17, active: false },
  { name: 'Charlie', age: 30, active: true },
  { name: 'David', age: 16, active: true }
];

// Jen dospělí (18+)
const adults = users.filter(user => user.age >= 18);
console.log(adults);
// → [
//   { name: 'Alice', age: 25, active: true },
//   { name: 'Charlie', age: 30, active: true }
// ]

// Jen aktivní uživatelé
const activeUsers = users.filter(user => user.active);
console.log(activeUsers);
// → [
//   { name: 'Alice', age: 25, active: true },
//   { name: 'Charlie', age: 30, active: true },
//   { name: 'David', age: 16, active: true }
// ]

// Kombinace podmínek
const activeAdults = users.filter(user => user.active && user.age >= 18);
console.log(activeAdults);
// → [
//   { name: 'Alice', age: 25, active: true },
//   { name: 'Charlie', age: 30, active: true }
// ]

Co se stalo?

  • Můžeš filtrovat objekty podle libovolné vlastnosti
  • user.active je zkratka pro user.active === true
  • Můžeš kombinovat podmínky pomocí && (a) nebo || (nebo)

Příklad 4: filter s indexem

const letters = ['a', 'b', 'c', 'd', 'e'];

// Jen prvky na sudých indexech (0, 2, 4)
const evenIndexes = letters.filter((letter, index) => index % 2 === 0);
console.log(evenIndexes);
// → ['a', 'c', 'e']

// Jen prvky po indexu 2
const afterIndex2 = letters.filter((letter, index) => index > 2);
console.log(afterIndex2);
// → ['d', 'e']

Co se stalo?

  • Predikát má 3 parametry:
    1. element - aktuální prvek
    2. index - index prvku
    3. array - celé pole (zřídka se používá)
  • Můžeš filtrovat podle indexu, ne jen podle hodnoty

Příklad 5: Odstranění falsy hodnot (compact)

const mixed = [0, 1, false, 2, '', 3, null, 4, undefined, 5, NaN];

// Odstraň všechny falsy hodnoty
const truthy = mixed.filter(Boolean);
console.log(truthy);
// → [1, 2, 3, 4, 5]

// Alternativa - explicitní
const truthy2 = mixed.filter(x => x);
console.log(truthy2);
// → [1, 2, 3, 4, 5]

Co se stalo?

  • filter(Boolean) - použij vestavěnou funkci Boolean jako predikát
  • Boolean(0) = false, Boolean(1) = true
  • Odstraní všechny falsy hodnoty: false, 0, '', null, undefined, NaN
  • Pozor: Odstraní i platné hodnoty jako 0 nebo ''!

Příklad 6: Kombinace filter a map (řetězení)

const numbers = [1, 2, 3, 4, 5, 6];

// Vezmi sudá čísla a vynásob je dvěma
const result = numbers
  .filter(n => n % 2 === 0)  // [2, 4, 6]
  .map(n => n * 2);          // [4, 8, 12]

console.log(result);
// → [4, 8, 12]

// Nebo v opačném pořadí
const result2 = numbers
  .map(n => n * 2)           // [2, 4, 6, 8, 10, 12]
  .filter(n => n > 5);       // [6, 8, 10, 12]

console.log(result2);
// → [6, 8, 10, 12]

Co se stalo?

  • Můžeš řetězit filter a map
  • Pořadí záleží - může ovlivnit výsledek i výkon
  • Optimalizace: Filtruj před map, pokud můžeš (méně prvků k transformaci)

TypeScript

TypeScript přidává typovou kontrolu predikátu a type guards pro zúžení typů.

Stejné příklady s typy

// Základní filtrování s typy
const numbers: number[] = [1, 2, 3, 4, 5, 6];
const even: number[] = numbers.filter((n: number): boolean => n % 2 === 0);

// TypeScript inferuje typy
const greaterThan5 = numbers.filter(n => n > 5);  // number[]

// Filtrování objektů s interface
interface User {
  name: string;
  age: number;
  active: boolean;
}

const users: User[] = [
  { name: 'Alice', age: 25, active: true },
  { name: 'Bob', age: 17, active: false }
];

const adults: User[] = users.filter(user => user.age >= 18);

// Type guard - zúžení typu
const mixed: (string | number | null)[] = [1, 'a', null, 2, 'b', null];

// Odstraň null hodnoty a zúž typ
const notNull: (string | number)[] = mixed.filter((x): x is string | number => x !== null);

// Type predicate - vlastní type guard
function isString(x: any): x is string {
  return typeof x === 'string';
}

const strings: string[] = mixed.filter(isString);  // jen stringy

// Chybová kontrola - predikát musí vracet boolean
const invalid = numbers.filter(n => n);  // ⚠️ Funguje, ale vrací number (truthy), ne boolean
const valid = numbers.filter(n => n > 0);  // ✅ Explicitně boolean

// Readonly pole
const readonly: readonly number[] = [1, 2, 3, 4, 5];
const filtered: number[] = readonly.filter(n => n > 2);  // ✅ OK - filter je immutabilní

TypeScript přidává:

  • Inference typů - TypeScript pozná typ prvku automaticky
  • Type guards - x is T zúží typ ve výsledném poli
  • Typovou kontrolu predikátu - musí vracet boolean (nebo truthy hodnotu)
  • IntelliSense - editor ti napovídá vlastnosti objektů
  • Prevenci chyb - chyby odhalíš při psaní

Rozdíl JS vs TS

JavaScript:

  • filter funguje bez typové kontroly
  • Nemáš type guards - typ se nezúží
  • Predikát může vracet cokoliv (truthy/falsy)
  • Flexibilnější, ale nebezpečnější

TypeScript:

  • Predikát je typově kontrolovaný
  • Type guards zužují typ ve výsledném poli
  • Lépe dokumentované záměry
  • Bezpečnější, prevence chyb
// JavaScript - typ se nezúží
const mixed = [1, 'a', null, 2];
const notNull = mixed.filter(x => x !== null);  // stále (number | string | null)[]

// TypeScript s type guard - typ se zúží
const mixed: (number | string | null)[] = [1, 'a', null, 2];
const notNull: (number | string)[] = mixed.filter((x): x is number | string => x !== null);

Tip

💡 filter + map vs kombinovaná operace:

// ✅ Čitelné - oddělené fáze
const result = numbers
  .filter(n => n > 5)
  .map(n => n * 2);

// ⚠️ Méně čitelné, ale rychlejší (jen jedna iterace)
const result = numbers.reduce((acc, n) => {
  if (n > 5) acc.push(n * 2);
  return acc;
}, []);

// Pro většinu případů preferuj filter + map (čitelnější)

💡 Filtruj PŘED map pro lepší výkon:

// ✅ Efektivnější - méně prvků k transformaci
const result = numbers
  .filter(n => n > 10)   // Zmenší pole
  .map(expensiveOp);     // Méně volání

// ❌ Neefektivní - transformuje všechny, pak filtruje
const result = numbers
  .map(expensiveOp)      // Mnoho volání
  .filter(n => n > 10);  // Filtruje až pak

💡 Odstraň duplicity pomocí filter:

const arr = [1, 2, 2, 3, 3, 3, 4];

// Ponechej jen první výskyt každé hodnoty
const unique = arr.filter((value, index, self) => self.indexOf(value) === index);
console.log(unique);
// → [1, 2, 3, 4]

// Moderní způsob - použij Set
const unique2 = [...new Set(arr)];  // Rychlejší

Kvíz

Co vypíše tento kód?

const arr = [0, 1, 2, 3, 4, 5];
const result = arr.filter(x => x);
console.log(result);

- 0 je falsy hodnota

- Predikát x => x vrací hodnotu x samotnou. filter ponechá jen truthy hodnoty. 0 je falsy, takže se odstraní. Všechny ostatní čísla (1, 2, 3, 4, 5) jsou truthy, takže projdou

- Nejsou odstraněny všechny hodnoty

- 0 je falsy, takže se odstraní

Důležité: Predikát může vracet libovolnou hodnotu, která se převede na boolean. 0false, 1true. Lepší je explicitně psát x => x !== 0 nebo x => x > 0.

Důležité: Predikát může vracet libovolnou hodnotu, která se převede na boolean. 0false, 1true. Lepší je explicitně psát x => x !== 0 nebo x => x > 0.

🎯 Závěrečný projekt

Po dokončení všech 8 dílů vytvoříte jednoduchou Todо aplikaci v čistém JavaScriptu. Naučíte se, jak aplikovat vše, co jste se naučili, na reálný projekt.

Zobrazit podrobnosti projektu →

Připraveni začít?

Zaregistrujte se a získejte přístup ke všem dílům tohoto seriálu

Kontaktujte mě

Informace o seriálu

Obtížnost

Délka

Cca 480 minut

Počet videí

8 videí + projekty

Certifikát

Po dokončení obdržíte certifikát


Lekce v této sekci


Struktura lekcí (souborový strom)

06. Typescript specifika
  • v přípravě
08. Moduly tridy
  • v přípravě
09. React zaklady
  • v přípravě
10. React hooks
  • v přípravě
12. Nextjs server
  • v přípravě
13. Databaze auth
  • v přípravě
14. Nextjs pokrocile
  • v přípravě