In dieser Reihe werde ich mit verschiedenen Fächern üben, um die funktionale Programmierung von Java
zu beherrschen. Dieses Mal werden wir zipWith
behandeln.
zip
und zipWith
zip
ist eine Standardfunktion der meisten Funktionssprachen, bei der die Elemente zweier Listen nacheinander kombiniert werden, um eine neue Liste zu erstellen.
Das Folgende ist ein Beispiel für "Haskell". Das erste Element "1" und "a" erzeugen einen Tapple "(1," a ")", und das zweite und dritte Element werden auf die gleiche Weise mit einer Gesamtlänge von 3 verarbeitet. Eine Liste der Taples wird erstellt.
zip
Prelude> zip [1,2,3] ['a','b','c']
[(1,'a'),(2,'b'),(3,'c')]
zipWith
ist eine Funktion höherer Ordnung, mit der Sie die Funktion angeben können, die beim Kombinieren von Elementen angewendet werden soll.
Im folgenden Beispiel wird eine Funktion namens "replizieren" angewendet, die das angegebene Element so oft wiederholt.
zipWith
Prelude> zipWith replicate [1,2,3] ['a','b','c']
["a","bb","ccc"]
zipWith
mit Java
Der Klarheit halber werde ich zunächst ein nicht allgemeines "_zipWith" schreiben, ohne Generika zu verwenden. Der Testcode, der dem Codebeispiel "zipWith" von "Haskell" im vorherigen Abschnitt entspricht, lautet wie folgt.
_zipMit Testcode
@Test
public void test_zipWith() {
List<String> l1 = Arrays.asList("a", "b", "c");
List<Integer> l2 = Arrays.asList(new Integer(1), new Integer(2), new Integer(3));
BiFunction<String, Integer, String> f = FunctionsTest::replicate;
List<String> zipped = Functions._zipWith(f, l1, l2);
assertNotNull(zipped);
assertEquals(3, zipped.size());
assertEquals("a", zipped.get(0));
assertEquals("bb", zipped.get(1));
assertEquals("ccc", zipped.get(2));
}
private static String replicate(String str, Integer n) {
return IntStream.range(0, n).mapToObj(i -> str).collect(Collectors.joining());
}
Die Implementierung von "_zipWith" ist wie folgt.
_zipWith
public static List<String> _zipWith(BiFunction<String, Integer, String> f, List<String> l1, List<Integer> l2) {
final int min;
if ((l1 == null || l1.size() == 0) || (l2 == null || l2.size() == 0)) {
return Collections.emptyList();
} else {
min = l1.size() <= l2.size() ? l1.size() : l2.size();
}
return IntStream.range(0, min)
.mapToObj(i -> f.apply(l1.get(i), l2.get(i)))
.collect(Collectors.toList());
}
Danach können Sie Generics zur Verallgemeinerung verwenden.
zipWith
public static <T, U, R> List<R> zipWith(BiFunction<T, U, R> f, List<T> l1, List<U> l2) {
final int min;
if ((l1 == null || l1.size() == 0) || (l2 == null || l2.size() == 0)) {
return Collections.emptyList();
} else {
min = l1.size() <= l2.size() ? l1.size() : l2.size();
}
return IntStream.range(0, min)
.mapToObj(i -> f.apply(l1.get(i), l2.get(i)))
.collect(Collectors.toList());
}
zip
mit Java
Sie können "zip" mit "zipWith" implementieren.
zip
public static <T, U> List<SimpleEntry<T, U>> zip(List<T> l1, List<U> l2) {
return zipWith((t, u) -> new SimpleEntry<>(t, u), l1, l2);
}
Die an zipWith
übergebene Funktion wird als eine Funktion angesehen, die zwei
Argumente empfängt und einen Taple generiert (in diesem Fall SimpleEntry) und in einem Lambda-Ausdruck beschrieben wird.
Der Beispielcode wird auf GitHub hochgeladen.
Recommended Posts