Dans cette série, je pratiquerai avec divers sujets dans le but de maîtriser la programmation fonctionnelle de Java
. Cette fois, nous couvrirons zipWith
.
zip
et zipWith
«zip» est une fonctionnalité standard de la plupart des langages fonctionnels qui combine les éléments de deux listes en séquence pour créer une nouvelle liste. Voici un exemple de «Haskell». Le premier élément "1" et "a" "produit un tapple" (1, "a") ", et les deuxième et troisième éléments sont traités de la même manière, avec une longueur totale de 3. Une liste de taples sera générée.
zip
Prelude> zip [1,2,3] ['a','b','c']
[(1,'a'),(2,'b'),(3,'c')]
zipWith
est une fonction d'ordre supérieur qui vous permet de spécifier la fonction à appliquer lors de la combinaison d'éléments.
L'exemple suivant applique une fonction appelée «replicate» qui répète l'élément spécifié le nombre de fois spécifié.
zipWith
Prelude> zipWith replicate [1,2,3] ['a','b','c']
["a","bb","ccc"]
zipWith
avec Java
Dans un premier temps, par souci de clarté, j'écrirai un _zipWith
à usage non général sans utiliser de génériques.
Le code de test équivalent à l'exemple de code «zipWith» de «Haskell» dans la section précédente est le suivant.
_zipAvec code de test
@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());
}
L'implémentation de _zipWith
est la suivante.
_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());
}
Après cela, vous pouvez utiliser les génériques pour la généralisation.
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
avec Java
Vous pouvez implémenter zip
en utilisant zipWith
.
Java
n'a pas de taple, donc dans le code ci-dessous, java.util.AbstractMap.SimpleEntry
est utilisé à la place.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);
}
La fonction passée à zipWith
est considérée comme une fonction qui reçoit deux
arguments et génère un taple (SimpleEntry dans ce cas), et est décrite dans une expression lambda.
L'exemple de code est téléchargé sur GitHub.
Recommended Posts