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 zipWithzip 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 JavaDer 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 JavaSie 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