Haskell: agregar una tupla a una lista de tuplas si aún no existe, de lo contrario, aumenta el valor existente de la tupla

Saturas

Tengo una tupla que representa un producto:

type Product = (String, Int, Float)

String es el nombre, Int la cantidad y Float el precio o valor.

Ahora quiero hacer lo siguiente: obtuve una lista de productos y en esa lista quiero agregar un nuevo producto. Pero si el Producto ya está en la Lista, solo quiero aumentar la cantidad. (Por ahora no me importa lo que pase si el precio / valor no es el mismo)

"Si ya está en la lista, aumente la cantidad de ese producto. De lo contrario, agréguelo a la lista"

Entrada de ejemplo: ("Cerveza", 9, 3) [("Cerveza", 1, 3), ("Leche", 3, 3), ("Té", 10, 3)]
Salida esperada: [("Cerveza ", 10, 3), (" Leche ", 3, 3), (" Té ", 10, 3)]
o
Entrada de ejemplo: (" Manzana ", 2, 1) [(" Cerveza ", 1, 3) , ("Leche", 3, 3), ("Té", 10, 3)]
Resultado esperado: [("Cerveza", 1, 3), ("Leche", 3, 3), ("Té", 10, 3), ("Apple", 2, 1)]
(La Lista no tiene orden, por lo que no importa dónde se encuentre el nuevo Producto dentro de la Lista)

addProduct :: Product -> [Product] -> [Product]

Suena bastante fácil y, de hecho, tengo un método de trabajo que hace esto:

-- check if a name is inside a List
nameInList :: String -> [Product] -> Bool
nameInList n [(a,b,c)]    = if (a == n) then True else False
nameInList n ((a,b,c):xs) = if (a == n) then True else nameInList n xs

-- add a product to a list if its not already in that list else just increase amount of that product
addProduct :: Product -> [Product] -> [Product]
addProduct (a,b,c) xs  = if nameInList a xs then newList else (a,b,c) : newList
  where newList = [ (a2,b2+b,c2) | (a2,b2,c2) <- xs, a2 == a ] ++ [ (a2,b2,c2) | (a2,b2,c2) <- xs, a2 /= a]

Pero me preguntaba si de alguna manera puedo lograr lo mismo usando la coincidencia de patrones y la recursividad. También siento que debería ser posible sin otra función que realice algunas comprobaciones.

[Editar: se eliminó la posible segunda pregunta al final]

Robin Zigmond

Siempre que sepa que su lista de productos nunca tendrá un nombre duplicado, esto es bastante simple con recursividad pura:

addProduct :: Product -> [Product] -> [Product]
addProduct p [] = [p]
addProduct product@(name, amount, price) (product'@(name', amount', price') : ps)
  | name == name' = (name, amount' + amount, price') : ps
  | otherwise = product' : addProduct product ps

(Tenga en cuenta que si el producto se agrega con un precio diferente al de la versión actualmente en la lista, esto deja el precio anterior en su lugar; lo dejaré según los requisitos de su negocio si esto es posible y, de ser así, qué debería suceder .)

Tenga en cuenta el uso de como patrones para permitir que las producttuplas se comparen con el patrón y, al mismo tiempo, conservar una forma de referirse a todo en el caso recursivo. Esto no es esencial, pero hace que el código sea mucho más legible. Y también he usado guardias en lugar de si-entonces-si no, esto es más una preferencia personal, pero creo que los Haskellers generalmente lo prefieren de esta manera.

Un par de pequeñas notas sobre su propio código:

  1. utilice nombres de variables comprensibles. Verá que he reemplazado (a, b, c)por (name, amount, price)porque esto explica claramente al lector lo que realmente representan los valores
  2. if (a == n) then True else Falsees redundante porque es exactamente lo mismo que simplemente a == n, por lo que debería usar la versión más corta y clara.

Este artículo se recopila de Internet, indique la fuente cuando se vuelva a imprimir.

En caso de infracción, por favor [email protected] Eliminar

Editado en
0

Déjame decir algunas palabras

0Comentarios
Iniciar sesiónRevisión de participación posterior

Artículos relacionados

TOP Lista

CalienteEtiquetas

Archivo