Podijelite popis na dijelove u Kotlinu
1. Uvod
Recimo da imamo niz poput [a B C D E F] i želimo podijeliti elemente u zasebne skupine, poput [[a B C D E F]] ili [[a B C D E F]].
U ovom uputstvu postići ćemo to istražujući neke razlike između Kotlinovih grupaBy, chunked, i prozorski.
2. Dijeljenje popisa na popis parova
Za naše primjere koristit ćemo dva popisa - jedan s parnim brojem elemenata i jedan s neparnim brojem elemenata:
val evenList = listOf (0, "a", 1, "b", 2, "c"); val unevenList = listOf (0, "a", 1, "b", 2, "c", 3);
Jasno, možemo podijeliti svoje evenList u točno tri para. Međutim, naša neujednačenaPopis imat će jedan dodatni element.
U ostatku ovog odjeljka vidjet ćemo razne implementacije za razdvajanje naša dva popisa, uključujući kako se bave dodatnim elementom u neujednačenaPopis.
2.1. Koristeći grupaBy
Prvo, provedimo rješenje s groupBy. Stvorit ćemo popis s rastućim brojevima i koristiti grupaBy da ih podijelimo:
val numberList = listOf (1, 2, 3, 4, 5, 6); numberList.groupBy {(it + 1) / 2} .vrijednosti
To daje željeni rezultat:
[[1, 2], [3, 4], [5, 6]]
Kako radi? Dobro, grupaBy izvršava isporučenu funkciju (it + 1) / 2 na svakom elementu:
- (1 + 1) / 2 = 1
- (2 + 1) / 2 = 1,5, što je zaokruženo na 1
- (3 + 1) / 2 = 2
- (4 + 1) / 2 = 2,5, što je zaokruženo na 2
- (5 + 1) / 2 = 3
- (6 + 1) / 2 = 3,5, što je zaokruženo na 3
Zatim, grupaBy grupira elemente s popisa koji su dali isti rezultat.
Sada, kada to učinimo s neravnim popisom:
val numberList = listOf (1, 2, 3, 4, 5, 6, 7); numberList.groupBy {(it + 1) / 2} .vrijednosti
Dobivamo sve parove i jedan dodatni element:
[[1, 2], [3, 4], [5, 6], [7]]
Ali, ako idemo malo dalje s nekim slučajnim brojevima:
val numberList = listOf (1, 3, 8, 20, 23, 30); numberList.groupBy {(it + 1) / 2} .vrijednosti
Dobit ćemo nešto što je potpuno nepoželjno:
[[1], [3], [8], [20], [23], [30]]
Razlog je jednostavan; primjenom (it + 1) / 2 funkcija na svakom elementu daje: 1, 2, 4, 10, 12, 15. Svi se rezultati razlikuju, tako da se niti jedan element ne grupira.
Kad koristimo svoje evenList ili neujednačenaPopis, još je gore - kod se ne sastavlja, jer se funkcija ne može primijeniti na Žice.
2.2. Koristeći grupaBy i withIndex
Stvarno, ako želimo grupirati proizvoljan popis u parove, ne želimo mijenjati vrijednost po našoj funkciji, ali indeks:
evenList.withIndex () .groupBy {it.index / 2} .map {it.value.map {it.value}}
Ovo vraća popis parova koje želimo:
[[0, "a"], [1, "b"], [2, "c"]]
Nadalje, ako koristimo neujednačenaPopis, čak dobivamo i naš zasebni element:
[[0, "a"], [1, "b"], [2, "c"], [3]]
2.3. Koristeći grupaBy S foldIndexed
Možemo ići korak dalje od pukog korištenja indeks i programirajte malo više sa foldIndexed da biste spremili neka izdvajanja:
evenList.foldIndexed (ArrayList(evenList.size / 2)) {index, acc, item -> if (index% 2 == 0) {acc.add (ArrayList (2))} acc.last (). add (item) acc}
Iako malo opširniji, the foldIndexed rješenje jednostavno izvodi operaciju na svakom elementu, dok je withIndex funkcija prvo kreira iterator i obavija svaki element.
2.4. Koristeći komadan
Ali, to možemo učiniti elegantnije komadan. Dakle, primijenimo metodu na našu evenList:
evenList.chunked (2)
The evenList pruža nam parove koje želimo:
[[0, "a"], [1, "b"], [2, "c"]]
Dok neujednačenaPopis daje nam parove i dodatni element:
[[0, "a"], [1, "b"], [2, "c"], [3]]
2.5. Koristeći prozorski
I komadan djeluje jako dobro, ali ponekad nam treba malo više kontrole.
Na primjer, možda ćemo trebati odrediti želimo li samo parove ili želimo uključiti dodatni element. The prozorski metoda nam pruža a djelomičniWindows Booleova, što ukazuje na to želimo li djelomični rezultat ili ne.
Prema zadanim postavkama, djelomičniWindows je lažno. Dakle, sljedeće izjave daju isti rezultat:
evenList.windowed (2, 2) unevenList.windowed (2, 2, false)
Oboje vraćaju popis bez zasebnog elementa:
[[0, "a"], [1, "b"], [2, "c"]]
Napokon, kad krenemo djelomičniWindows do pravi uključiti djelomični rezultat:
unevenList.windowed (2, 2, istina)
Dobit ćemo popis parova plus zasebni element:
[[0, "a"], [1, "b"], [2, "c"], [3]]
3. Zaključak
Koristeći grupaBy je lijepa vježba programiranja, ali može biti sklona pogreškama. Neke se pogreške mogu riješiti jednostavnim korištenjem indeks.
Za optimizaciju koda možemo čak i koristiti foldIndexed. Međutim, to rezultira još više koda. Srećom, komadan metoda nudi nam istu funkcionalnost odmah po narudžbi.
Štoviše, prozorski metoda pruža dodatne mogućnosti konfiguracije. Ako je moguće, najbolje je koristiti komadan metodu, a ako trebamo dodatnu konfiguraciju, trebali bismo koristiti prozorski metoda.
Kao i obično, puni izvorni kod dostupan je na GitHubu.