Atraskite funkcinio programavimo galią su JavaScript masyvais. Išmokite efektyviai transformuoti, filtruoti ir redukuoti duomenis naudojant integruotus metodus.
Funkcinio programavimo su JavaScript masyvais įvaldymas
Nuolat besikeičiančioje interneto kūrimo srityje JavaScript išlieka kertiniu akmeniu. Nors objektinio ir imperatyvaus programavimo paradigmos ilgą laiką dominavo, funkcinis programavimas (FP) įgauna vis didesnį populiarumą. FP pabrėžia nekintamumą, grynąsias funkcijas ir deklaratyvų kodą, o tai lemia patikimesnes, lengviau prižiūrimas ir nuspėjamas programas. Vienas iš galingiausių būdų pritaikyti funkcinį programavimą JavaScript yra pasinaudoti jo natūraliais masyvų metodais.
Šis išsamus gidas paaiškins, kaip galite panaudoti funkcinio programavimo principų galią naudojant JavaScript masyvus. Mes išnagrinėsime pagrindines sąvokas ir parodysime, kaip jas taikyti naudojant metodus, tokius kaip map
, filter
ir reduce
, pakeisdami jūsų požiūrį į duomenų manipuliavimą.
Kas yra funkcinis programavimas?
Prieš gilinantis į JavaScript masyvus, trumpai apibrėžkime funkcinį programavimą. Iš esmės, FP yra programavimo paradigma, kuri skaičiavimą traktuoja kaip matematinių funkcijų vertinimą ir vengia būsenos keitimo bei kintamų duomenų. Pagrindiniai principai apima:
- Grynosios funkcijos: Grynoji funkcija visada sugeneruoja tą pačią išvestį tai pačiai įvesčiai ir neturi šalutinių poveikių (ji nekeičia išorinės būsenos).
- Nekintamumas: Sukurti duomenys negali būti pakeisti. Vietoj esamų duomenų modifikavimo, sukuriami nauji duomenys su norimais pakeitimais.
- Pirmos klasės funkcijos: Funkcijos gali būti traktuojamos kaip bet kuris kitas kintamasis – jos gali būti priskirtos kintamiesiems, perduotos kaip argumentai kitoms funkcijoms ir grąžintos iš funkcijų.
- Deklaratyvus vs. Imperatyvus: Funkcinis programavimas linksta prie deklaratyvaus stiliaus, kuriame aprašote, *ką* norite pasiekti, o ne imperatyvaus stiliaus, kuriame detaliai nurodote, *kaip* tai pasiekti žingsnis po žingsnio.
Šių principų taikymas gali padėti sukurti kodą, kurį lengviau suprasti, testuoti ir derinti, ypač sudėtingose programose. JavaScript masyvų metodai puikiai tinka šioms koncepcijoms įgyvendinti.
JavaScript masyvų metodų galia
JavaScript masyvai turi gausų integruotų metodų rinkinį, leidžiantį atlikti sudėtingas duomenų manipuliacijas nenaudojant tradicinių ciklų (pvz., for
ar while
). Šie metodai dažnai grąžina naujus masyvus, skatindami nekintamumą, ir priima atgalinio iškvietimo (callback) funkcijas, įgalindami funkcinį požiūrį.
Panagrinėkime pagrindinius funkcinius masyvų metodus:
1. Array.prototype.map()
Metodas map()
sukuria naują masyvą, užpildytą rezultatais, gautais iškvietus pateiktą funkciją kiekvienam pradinio masyvo elementui. Jis idealiai tinka kiekvieno masyvo elemento transformavimui į kažką naujo.
Sintaksė:
array.map(callback(currentValue[, index[, array]])[, thisArg])
callback
: Funkcija, kuri bus vykdoma kiekvienam elementui.currentValue
: Dabartinis masyve apdorojamas elementas.index
(pasirinktinai): Dabartinio apdorojamo elemento indeksas.array
(pasirinktinai): Masyvas, kuriam buvo iškviestasmap
metodas.thisArg
(pasirinktinai): Reikšmė, kuri bus naudojama kaipthis
vykdantcallback
.
Pagrindinės savybės:
- Grąžina naują masyvą.
- Originalus masyvas lieka nepakitęs (nekintamumas).
- Naujas masyvas turės tokį patį ilgį kaip ir originalus masyvas.
- Atgalinio iškvietimo funkcija turėtų grąžinti transformuotą reikšmę kiekvienam elementui.
Pavyzdys: Kiekvieno skaičiaus padvigubinimas
Įsivaizduokite, kad turite skaičių masyvą ir norite sukurti naują masyvą, kuriame kiekvienas skaičius yra padvigubintas.
const numbers = [1, 2, 3, 4, 5];
// Naudojamas map transformacijai
const doubledNumbers = numbers.map(number => number * 2);
console.log(numbers); // Išvestis: [1, 2, 3, 4, 5] (originalus masyvas nepakito)
console.log(doubledNumbers); // Išvestis: [2, 4, 6, 8, 10]
Pavyzdys: Savybių išgavimas iš objektų
Dažnas panaudojimo atvejis – konkrečių savybių išgavimas iš objektų masyvo. Tarkime, turime vartotojų sąrašą ir norime gauti tik jų vardus.
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const userNames = users.map(user => user.name);
console.log(userNames); // Išvestis: ['Alice', 'Bob', 'Charlie']
2. Array.prototype.filter()
Metodas filter()
sukuria naują masyvą su visais elementais, kurie praeina pateiktos funkcijos įgyvendintą testą. Jis naudojamas elementams pasirinkti pagal tam tikrą sąlygą.
Sintaksė:
array.filter(callback(element[, index[, array]])[, thisArg])
callback
: Funkcija, kuri bus vykdoma kiekvienam elementui. Ji turėtų grąžintitrue
, kad elementas būtų paliktas, arbafalse
, kad būtų atmestas.element
: Dabartinis masyve apdorojamas elementas.index
(pasirinktinai): Dabartinio elemento indeksas.array
(pasirinktinai): Masyvas, kuriam buvo iškviestasfilter
metodas.thisArg
(pasirinktinai): Reikšmė, kuri bus naudojama kaipthis
vykdantcallback
.
Pagrindinės savybės:
- Grąžina naują masyvą.
- Originalus masyvas lieka nepakitęs (nekintamumas).
- Naujas masyvas gali turėti mažiau elementų nei originalus masyvas.
- Atgalinio iškvietimo funkcija turi grąžinti loginę (boolean) reikšmę.
Pavyzdys: Lyginių skaičių filtravimas
Filtruokime skaičių masyvą, kad paliktume tik lyginius skaičius.
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// Naudojamas filter lyginiams skaičiams atrinkti
const evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(numbers); // Išvestis: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(evenNumbers); // Išvestis: [2, 4, 6, 8, 10]
Pavyzdys: Aktyvių vartotojų filtravimas
Iš mūsų vartotojų masyvo išfiltruokime vartotojus, kurie yra pažymėti kaip aktyvūs.
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true },
{ id: 4, name: 'David', isActive: false }
];
const activeUsers = users.filter(user => user.isActive);
console.log(activeUsers);
/* Išvestis:
[
{ id: 1, name: 'Alice', isActive: true },
{ id: 3, name: 'Charlie', isActive: true }
]
*/
3. Array.prototype.reduce()
Metodas reduce()
vykdo vartotojo pateiktą „reduktoriaus“ (reducer) atgalinio iškvietimo funkciją kiekvienam masyvo elementui iš eilės, perduodamas grąžinamąją reikšmę iš skaičiavimo su ankstesniu elementu. Galutinis reduktoriaus vykdymo per visus masyvo elementus rezultatas yra viena reikšmė.
Tai, be abejonės, universaliausias iš masyvų metodų ir yra daugelio funkcinio programavimo modelių pagrindas, leidžiantis „redukuoti“ masyvą iki vienos reikšmės (pvz., sumos, sandaugos, skaičiaus arba net naujo objekto ar masyvo).
Sintaksė:
array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
callback
: Funkcija, kuri bus vykdoma kiekvienam elementui.accumulator
: Reikšmė, gauta iš ankstesnio atgalinio iškvietimo funkcijos iškvietimo. Pirmojo iškvietimo metu tai yrainitialValue
, jei ji pateikta; kitu atveju, tai pirmasis masyvo elementas.currentValue
: Dabartinis apdorojamas elementas.index
(pasirinktinai): Dabartinio elemento indeksas.array
(pasirinktinai): Masyvas, kuriam buvo iškviestasreduce
metodas.initialValue
(pasirinktinai): Pradinė reikšmė, kuri bus naudojama kaip pirmasis argumentas pirmajamcallback
iškvietimui. JeiinitialValue
nepateikta, pirmasis masyvo elementas bus naudojamas kaip pradinėaccumulator
reikšmė, o iteracija prasidės nuo antrojo elemento.
Pagrindinės savybės:
- Grąžina vieną reikšmę (kuri taip pat gali būti masyvas ar objektas).
- Originalus masyvas lieka nepakitęs (nekintamumas).
initialValue
yra labai svarbi aiškumui ir klaidų išvengimui, ypač su tuščiais masyvais arba kai akumuliatoriaus tipas skiriasi nuo masyvo elementų tipo.
Pavyzdys: Skaičių sumavimas
Susumuokime visus skaičius mūsų masyve.
const numbers = [1, 2, 3, 4, 5];
// Naudojamas reduce skaičiams sumuoti
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 0 yra pradinė reikšmė (initialValue)
console.log(sum); // Išvestis: 15
Paaiškinimas:
- 1 iškvietimas:
accumulator
yra 0,currentValue
yra 1. Grąžina 0 + 1 = 1. - 2 iškvietimas:
accumulator
yra 1,currentValue
yra 2. Grąžina 1 + 2 = 3. - 3 iškvietimas:
accumulator
yra 3,currentValue
yra 3. Grąžina 3 + 3 = 6. - Ir taip toliau, kol apskaičiuojama galutinė suma.
Pavyzdys: Objektų grupavimas pagal savybę
Galime naudoti reduce
, kad paverstume objektų masyvą į objektą, kuriame reikšmės sugrupuotos pagal tam tikrą savybę. Sugrupuokime mūsų vartotojus pagal jų `isActive` būseną.
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true },
{ id: 4, name: 'David', isActive: false }
];
const groupedUsers = users.reduce((acc, user) => {
const status = user.isActive ? 'active' : 'inactive';
if (!acc[status]) {
acc[status] = [];
}
acc[status].push(user);
return acc;
}, {}); // Tuščias objektas {} yra pradinė reikšmė (initialValue)
console.log(groupedUsers);
/* Išvestis:
{
active: [
{ id: 1, name: 'Alice', isActive: true },
{ id: 3, name: 'Charlie', isActive: true }
],
inactive: [
{ id: 2, name: 'Bob', isActive: false },
{ id: 4, name: 'David', isActive: false }
]
}
*/
Pavyzdys: Pasikartojimų skaičiavimas
Suskaičiuokime kiekvieno vaisiaus pasikartojimo dažnį sąraše.
const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];
const fruitCounts = fruits.reduce((acc, fruit) => {
acc[fruit] = (acc[fruit] || 0) + 1;
return acc;
}, {});
console.log(fruitCounts); // Išvestis: { apple: 3, banana: 2, orange: 1 }
4. Array.prototype.forEach()
Nors forEach()
negrąžina naujo masyvo ir dažnai laikomas labiau imperatyviu, nes jo pagrindinis tikslas yra įvykdyti funkciją kiekvienam masyvo elementui, jis vis tiek yra pagrindinis metodas, kuris vaidina vaidmenį funkciniuose modeliuose, ypač kai reikalingi šalutiniai poveikiai arba kai iteruojama be transformuotos išvesties poreikio.
Sintaksė:
array.forEach(callback(element[, index[, array]])[, thisArg])
Pagrindinės savybės:
- Grąžina
undefined
. - Įvykdo pateiktą funkciją vieną kartą kiekvienam masyvo elementui.
- Dažnai naudojamas šalutiniams poveikiams, pvz., įrašymui į konsolę ar DOM elementų atnaujinimui.
Pavyzdys: Kiekvieno elemento registravimas
const messages = ['Hello', 'Functional', 'World'];
messages.forEach(message => console.log(message));
// Išvestis:
// Hello
// Functional
// World
Pastaba: Transformacijoms ir filtravimui pirmenybė teikiama map
ir filter
dėl jų nekintamumo ir deklaratyvios prigimties. Naudokite forEach
, kai specialiai reikia atlikti veiksmą kiekvienam elementui, nerenkant rezultatų į naują struktūrą.
5. Array.prototype.find()
ir Array.prototype.findIndex()
Šie metodai naudingi ieškant konkrečių elementų masyve.
find()
: Grąžina pirmo elemento, atitinkančio pateiktą testavimo funkciją, reikšmę. Jei jokia reikšmė neatitinka testavimo funkcijos, grąžinamasundefined
.findIndex()
: Grąžina pirmo elemento, atitinkančio pateiktą testavimo funkciją, indeksą. Kitu atveju grąžina -1, nurodydamas, kad joks elementas neatitiko testo.
Pavyzdys: Vartotojo paieška
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Charlie' }
];
const bob = users.find(user => user.name === 'Bob');
const bobIndex = users.findIndex(user => user.name === 'Bob');
const nonExistentUser = users.find(user => user.name === 'David');
const nonExistentIndex = users.findIndex(user => user.name === 'David');
console.log(bob); // Išvestis: { id: 2, name: 'Bob' }
console.log(bobIndex); // Išvestis: 1
console.log(nonExistentUser); // Išvestis: undefined
console.log(nonExistentIndex); // Išvestis: -1
6. Array.prototype.some()
ir Array.prototype.every()
Šie metodai tikrina, ar visi masyvo elementai atitinka pateiktos funkcijos įgyvendintą testą.
some()
: Patikrina, ar bent vienas masyvo elementas atitinka pateiktos funkcijos įgyvendintą testą. Grąžina loginę reikšmę.every()
: Patikrina, ar visi masyvo elementai atitinka pateiktos funkcijos įgyvendintą testą. Grąžina loginę reikšmę.
Pavyzdys: Vartotojo būsenos tikrinimas
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true }
];
const hasInactiveUser = users.some(user => !user.isActive);
const allAreActive = users.every(user => user.isActive);
console.log(hasInactiveUser); // Išvestis: true (nes Bob yra neaktyvus)
console.log(allAreActive); // Išvestis: false (nes Bob yra neaktyvus)
const allUsersActive = users.filter(user => user.isActive).length === users.length;
console.log(allUsersActive); // Išvestis: false
// Alternatyva naudojant every tiesiogiai
const allUsersActiveDirect = users.every(user => user.isActive);
console.log(allUsersActiveDirect); // Išvestis: false
Masyvų metodų grandininis jungimas sudėtingoms operacijoms
Tikroji funkcinio programavimo su JavaScript masyvais galia atsiskleidžia, kai šiuos metodus sujungiame į grandinę. Kadangi dauguma šių metodų grąžina naujus masyvus (išskyrus forEach
), galite sklandžiai perduoti vieno metodo išvestį į kito įvestį, sukurdami elegantiškus ir lengvai skaitomus duomenų apdorojimo vamzdynus.
Pavyzdys: Aktyvių vartotojų vardų radimas ir jų ID padvigubinimas
Raskime visus aktyvius vartotojus, ištraukime jų vardus, o tada sukurkime naują masyvą, kuriame prie kiekvieno vardo pridedamas skaičius, nurodantis jo indeksą *išfiltruotame* sąraše, o jų ID yra padvigubinti.
const users = [
{ id: 1, name: 'Alice', isActive: true },
{ id: 2, name: 'Bob', isActive: false },
{ id: 3, name: 'Charlie', isActive: true },
{ id: 4, name: 'David', isActive: true },
{ id: 5, name: 'Eve', isActive: false }
];
const processedActiveUsers = users
.filter(user => user.isActive) // Gauti tik aktyvius vartotojus
.map((user, index) => ({ // Transformuoti kiekvieną aktyvų vartotoją
name: `${index + 1}. ${user.name}`,
doubledId: user.id * 2
}));
console.log(processedActiveUsers);
/* Išvestis:
[
{ name: '1. Alice', doubledId: 2 },
{ name: '2. Charlie', doubledId: 6 },
{ name: '3. David', doubledId: 8 }
]
*/
Šis grandininis požiūris yra deklaratyvus: mes nurodome žingsnius (filtruoti, tada transformuoti) be aiškaus ciklų valdymo. Jis taip pat yra nekintamas, nes kiekvienas žingsnis sukuria naują masyvą ar objektą, palikdamas originalų users
masyvą nepaliestą.
Nekintamumas praktikoje
Funkcinis programavimas labai remiasi nekintamumu. Tai reiškia, kad vietoj esamų duomenų struktūrų keitimo, jūs kuriate naujas su norimais pakeitimais. JavaScript masyvų metodai, tokie kaip map
, filter
ir slice
, iš prigimties tai palaiko, grąžindami naujus masyvus.
Kodėl nekintamumas yra svarbus?
- Nuspėjamumas: Kodą tampa lengviau suprasti, nes nereikia sekti bendros kintamos būsenos pokyčių.
- Derinimas: Kai atsiranda klaidų, lengviau nustatyti problemos šaltinį, kai duomenys nėra netikėtai modifikuojami.
- Našumas: Tam tikruose kontekstuose (pvz., su būsenos valdymo bibliotekomis kaip Redux arba React), nekintamumas leidžia efektyviai aptikti pokyčius.
- Lygiagretumas: Nekintamos duomenų struktūros yra iš prigimties saugios gijoms (thread-safe), supaprastinant lygiagretųjį programavimą.
Kai reikia atlikti operaciją, kuri tradiciškai pakeistų masyvą (pvz., pridėti ar pašalinti elementą), galite pasiekti nekintamumą naudodami metodus, tokius kaip slice
, „spread“ sintaksę (...
), arba derindami kitus funkcinius metodus.
Pavyzdys: Elemento pridėjimas nekintamu būdu
const originalArray = [1, 2, 3];
// Imperatyvus būdas (keičia originalų masyvą)
// originalArray.push(4);
// Funkcinis būdas naudojant „spread“ sintaksę
const newArrayWithPush = [...originalArray, 4];
console.log(originalArray); // Išvestis: [1, 2, 3]
console.log(newArrayWithPush); // Išvestis: [1, 2, 3, 4]
// Funkcinis būdas naudojant slice ir sujungimą (dabar retesnis)
const newArrayWithSlice = originalArray.slice(0, originalArray.length).concat(4);
console.log(newArrayWithSlice); // Išvestis: [1, 2, 3, 4]
Pavyzdys: Elemento pašalinimas nekintamu būdu
const originalArray = [1, 2, 3, 4, 5];
// Pašalinti elementą su indeksu 2 (reikšmė 3)
// Funkcinis būdas naudojant slice ir „spread“ sintaksę
const newArrayAfterSplice = [
...originalArray.slice(0, 2),
...originalArray.slice(3)
];
console.log(originalArray); // Išvestis: [1, 2, 3, 4, 5]
console.log(newArrayAfterSplice); // Išvestis: [1, 2, 4, 5]
// Naudojant filter konkrečiai reikšmei pašalinti
const newValueToRemove = 3;
const arrayWithoutValue = originalArray.filter(item => item !== newValueToRemove);
console.log(arrayWithoutValue); // Išvestis: [1, 2, 4, 5]
Gerosios praktikos ir pažangios technikos
Kai labiau įprasite prie funkcinių masyvų metodų, apsvarstykite šias praktikas:
- Skaitymas pirmiausia: Nors grandininis sujungimas yra galingas, pernelyg ilgos grandinės gali tapti sunkiai skaitomos. Apsvarstykite galimybę sudėtingas operacijas suskaidyti į mažesnes, pavadintas funkcijas arba naudoti tarpinius kintamuosius.
- Supraskite
reduce
lankstumą: Atminkite, kadreduce
gali kurti masyvus ar objektus, o ne tik vieną reikšmę. Dėl to jis yra neįtikėtinai universalus sudėtingoms transformacijoms. - Venkite šalutinių poveikių atgalinio iškvietimo funkcijose: Stenkitės, kad jūsų
map
,filter
irreduce
atgalinio iškvietimo funkcijos būtų grynosios. Jei reikia atlikti veiksmą su šalutiniais poveikiais,forEach
dažnai yra tinkamesnis pasirinkimas. - Naudokite rodyklines funkcijas: Rodyklinės funkcijos (
=>
) suteikia glaustą sintaksę atgalinio iškvietimo funkcijoms ir skirtingai valdo `this` susiejimą, todėl dažnai idealiai tinka funkciniams masyvų metodams. - Apsvarstykite bibliotekas: Pažangesniems funkcinio programavimo modeliams arba jei intensyviai dirbate su nekintamumu, gali būti naudingos bibliotekos, tokios kaip Lodash/fp, Ramda ar Immutable.js, nors jos nėra būtinos norint pradėti dirbti su funkcinėmis masyvų operacijomis moderniame JavaScript.
Pavyzdys: Funkcinis požiūris į duomenų agregavimą
Įsivaizduokite, kad turite pardavimų duomenis iš skirtingų regionų ir norite apskaičiuoti bendrus pardavimus kiekvienam regionui, o tada rasti regioną su didžiausiais pardavimais.
const salesData = [
{ region: 'North', amount: 100 },
{ region: 'South', amount: 150 },
{ region: 'North', amount: 120 },
{ region: 'East', amount: 200 },
{ region: 'South', amount: 180 },
{ region: 'North', amount: 90 }
];
// 1. Apskaičiuoti bendrus pardavimus pagal regioną naudojant reduce
const salesByRegion = salesData.reduce((acc, sale) => {
acc[sale.region] = (acc[sale.region] || 0) + sale.amount;
return acc;
}, {});
// salesByRegion bus: { North: 310, South: 330, East: 200 }
// 2. Konvertuoti agreguotą objektą į objektų masyvą tolesniam apdorojimui
const salesArray = Object.keys(salesByRegion).map(region => ({
region: region,
totalAmount: salesByRegion[region]
}));
// salesArray bus: [
// { region: 'North', totalAmount: 310 },
// { region: 'South', totalAmount: 330 },
// { region: 'East', totalAmount: 200 }
// ]
// 3. Rasti regioną su didžiausiais pardavimais naudojant reduce
const highestSalesRegion = salesArray.reduce((max, current) => {
return current.totalAmount > max.totalAmount ? current : max;
}, { region: '', totalAmount: -Infinity }); // Inicijuoti su labai mažu skaičiumi
console.log('Pardavimai pagal regioną:', salesByRegion);
console.log('Pardavimų masyvas:', salesArray);
console.log('Regionas su didžiausiais pardavimais:', highestSalesRegion);
/*
Išvestis:
Pardavimai pagal regioną: { North: 310, South: 330, East: 200 }
Pardavimų masyvas: [
{ region: 'North', totalAmount: 310 },
{ region: 'South', totalAmount: 330 },
{ region: 'East', totalAmount: 200 }
]
Regionas su didžiausiais pardavimais: { region: 'South', totalAmount: 330 }
*/
Išvada
Funkcinis programavimas su JavaScript masyvais yra ne tik stilistinis pasirinkimas; tai galingas būdas rašyti švaresnį, labiau nuspėjamą ir patikimesnį kodą. Pradėję naudoti tokius metodus kaip map
, filter
ir reduce
, galite efektyviai transformuoti, užklausti ir agreguoti duomenis, laikydamiesi pagrindinių funkcinio programavimo principų, ypač nekintamumo ir grynųjų funkcijų.
Tęsiant kelionę JavaScript kūrimo srityje, šių funkcinių modelių integravimas į kasdienę darbo eigą neabejotinai padės kurti lengviau prižiūrimas ir labiau keičiamo mastelio programas. Pradėkite eksperimentuoti su šiais masyvų metodais savo projektuose ir netrukus atrasite jų didžiulę vertę.