2011-03-25 10 views
5

Quiero escribir una función que divide listas en sublistas según qué elementos satisfacen una propiedad determinada p. Mi pregunta es a qué llamar la función. Daré ejemplos en Haskell, pero el mismo problema surgiría en F # o ML.¿Cómo llamar a una función que divide listas?

split :: (a -> Bool) -> [a] -> [[a]] --- split lists into list of sublists 

Las sublistas, concatenados, son la lista original:

concat (split p xss) == xs 

Cada sublista satisface la propiedad initial_p_only p, es decir, (A) la lista secundaria comienza con un elemento que satisface p — y por lo tanto es no está vacío, y (B) no hay otros elementos satisfacen p:

initial_p_only :: (a -> Bool) -> [a] -> Bool 
initial_p_only p [] = False 
initial_p_only p (x:xs) = p x && all (not . p) xs 

Así sea precisa al respecto,

all (initial_p_only p) (split p xss) 

Si el primer elemento de la lista original no satisface p, dividida falla.

Esta función debe llamarse diferente a split. ¿Cómo debería llamarlo?

+0

groupBy no parece del todo correcto. grupoPodría funcionar. –

+0

splitBy? splitBefore/After? – Daniel

+4

Me encanta cómo escribió una especificación formal sin una implementación. – luqui

Respuesta

12

creo que la función que se está describiendo es breakBefore del paquete list-grouping.

Data.List.Grouping: http://hackage.haskell.org/packages/archive/list-grouping/0.1.1/doc/html/Data-List-Grouping.html

ghci> breakBefore even [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,8,4,6,2,6] 
[[3,1],[4,1,5,9],[2],[6,5,3,5],[8,9,7,9,3],[2,3],[8],[4],[6],[2],[6]] 
+0

+1 para no solo dar un nombre, sino una implementación ya existente de la función. –

+1

Aterrador. Mi código ya ha sido escrito. Gracias amablemente –

+0

No me gustan las variantes simples de 'break' ya que' break' en sí produce una tupla y no una lista. Tal vez 'se rompa antes ', excepto que el plural es demasiado sutil. 'unfoldBreaks' es un nombre bastante literal. – sclv

2

me gusta bastante un nombre basado en el término "ruptura", como sugiere Adamse. Hay bastantes variantes posibles de la función. Esto es lo que esperaría (basado en la denominación utilizada en las bibliotecas F #).

una función llamada simplemente breakBefore tomaría un elemento ante el que debe romper:

breakBefore :: Eq a => a -> [a] -> [[a]] 

Una función con el sufijo With tomaría algún tipo de función que especifica directamente cuándo romper. En caso de brekaing Esta es la función a -> Bool que quería:

breakBeforeWith :: (a -> Bool) -> [a] -> [[a]] 

También se podría imaginar una función con By sufijo tomaría un selector de llave y romper cuando cambia la clave (que es un poco como group by, pero puede tener varios grupos con la misma clave):

breakBeforeBy :: Eq k => (a -> k) -> [a] -> [[a]] 

admito que los nombres son cada vez un poco largo - y tal vez la única función que es realmente útil es el que usted quería. Sin embargo, las bibliotecas F # parecen estar usando este patrón de manera bastante consistente (por ejemplo, hay sort, sortBy tomando el selector de llave y sortWith teniendo la función de comparador).

Quizás es posible tener estas tres variantes para más funciones de procesamiento de listas (y es una buena idea tener un patrón de nombres consistente para estos tres tipos).

+0

Simplemente llamé a mi 'break: ('a -> bool) ->' a list -> 'a list *' a list' –

Cuestiones relacionadas