2008-10-21 14 views
7

A menudo necesito ejecutar reducir (también llamado foldl/foldr, según sus contextos) en java para agregar elementos de un Itterable.¿Hay una implementación Java de tipo 'reducir'?

Reducir lleva una colección/iterable/etc, una función de dos parámetros y un valor de inicio opcional (según los detalles de implementación). La función se aplica sucesivamente a un elemento de la colección y al resultado de la invocación anterior de reducir hasta que todos los elementos hayan sido procesados, y devuelve el valor final.

¿Hay una implementación de tipo seguro de reducir en cualquier API común de Java? Google Collectionsparece como debería tener uno, pero no he podido encontrarlo. (posiblemente porque no sé qué otros nombres usaría.)

Respuesta

2

que probablemente se podría rodar su propia genérica con bastante facilidad, sobre la base de su descripción:

public interface Reducer<A, T> 
{ 
    public A foldIn(A accum, T next); 
} 

Luego, utilizando el patrón de estrategia:

public class Reductor<A, T> 
{ 
    private Reducer<A, T> worker; 
    public Reductor<A, T>(Reducer<A, T> worker) 
    { 
     this.worker = worker; 
    } 

    public A fold(A rval, Iterator<T> itr) 
    { 
     while(itr.hasNext()) 
     { 
      A rval = worker.foldIn(rval, itr.next()); 
     } 
     return rval; 
    } 
} 

Estoy seguro de que hay un montón de errores de sintaxis pero ese es el punto principal (hay algunas opciones que podría tomar sobre cómo obtener el valor del acumulador vacío. Luego, para usarlo en un iterador concreto, simplemente defina su Reductor sobre la marcha:

Reductor r = new Reductor<A, T>(new Reducer<A, T>() 
{ 
    public A foldIn(A prev, T next) 
    { 
     A rval; 
     //do stuff... 
     return rval; 
    } 
} 

A fold = r.fold(new A(), collection.getIterator()); 

dependiendo de cómo funciona su iterador esto puede doblar hacia la izquierda o doblar hacia la derecha siempre que el iterador vaya en la dirección correcta.

Espero que esto ayude.

+0

que es una forma de hacerlo - Todavía no estoy convencido de que necesite una versión generalmente aplicable de reducir lo suficiente como para justificar el costo de desarrollo/prueba/mantenimiento de mi propia versión. – rcreswick

+0

muy bien hecho, pero las contorsiones que necesitas para hacer esto en Java son suficientes para hacerme llorar. –

+0

I * think * va a haber una biblioteca complementaria para Google Collections que proporcione herramientas de lenguaje funcional como esta, pero por ahora, esta es la mejor respuesta que he encontrado. – rcreswick

1

Pruebe el commons functor package. Ha estado en el cajón de arena para siempre, pero creo que hará lo que quieras.

+0

que parece interesante, pero no se ve como que va a encajar en la biblioteca de colecciones de Java existentes que bien. Si nada más aparece, profundizaré en ello más profundamente. – rcreswick

+1

Sí, es complicado. Creo que puedes hacer papas fritas con ella. Parece que la clave para integrarse con colecciones es la clase IteratorToGeneratorAdapter. – sblundy

2

Sobre la base de la sugerencia de Lucas, aquí es una implementación de Java de fiar:

public interface Reducer<A,T> 
{ 
    A foldIn(A accum, T next); 
} 

public static <T> T reduce(final Reducer<T,T> reducer, 
     final Iterable<? extends T> i) 
{ 
    T result = null; 
    final Iterator<? extends T> iter = i.iterator(); 
    if (iter.hasNext()) 
    { 
     result = iter.next(); 
     while (iter.hasNext()) 
     { 
      result = reducer.foldIn(result, iter.next()); 
     } 
    } 
    return result; 
} 

public static <A,T> A reduce(final Reducer<A,T> reducer, 
     final Iterable<? extends T> i, 
     final A initializer) 
{ 
    A result = initializer; 
    final Iterator<? extends T> iter = i.iterator(); 
    while (iter.hasNext()) 
    { 
     result = reducer.foldIn(result, iter.next()); 
    } 
    return result; 
} 
Cuestiones relacionadas