#haskell #functional-programming #lazy-evaluation
#haskell #функциональное программирование #ленивая оценка
Вопрос:
Я пытаюсь превратить список кортежей в список списков. Например, если у меня есть список [(9,1), (6,3), (4,1)]
, то это превратится в [[9, 6, 4],[6],[6]]
. Происходит то, что в списке кортежей [(a,b)]
, a
представляет собой число от 0 до 9 и b
представляет вхождение этого числа, a
всегда будет уникальным.
Что я пытаюсь сделать, так это пройтись по списку n
раз, где n = maximum b in the list of tuples.
каждый раз, когда я просматриваю список, я беру a
и помещаю его в список, затем уменьшаю b
на 1. Если b == 0
тогда я просто пропускаю это.
Итак, из моего примера я беру [9,6,4]
и добавляю их в список, затем уменьшаю b
значение каждого из них, так что теперь список будет выглядеть так [(9,0),(6,2),(4,0)]
. Затем, повторяя, я беру [6]
, список кортежей теперь выглядит так [(9,0), (6,1), (4,0)]
. Наконец, сделайте [6]
последний раз, и теперь когда-либо b
в списке кортежей есть 0
, так что это сделано.
Я создал функцию, которая принимает 1-й элемент из списка кортежей, если b
значение >= 1, но я не знаю, как я могу повторить это по обновленному списку со всеми `b — 1′ для каждого кортежа.
turnIntList :: [(Integer, Integer)] -> [[Integer]]
turnIntList [] = []
turnIntList x = ([map ((a, b) -> case (a,b) of _ | b >= 1 -> a | otherwise -> -1) x])
Я также попытался создать другую вспомогательную функцию, которая принимает список кортежей и преобразует их в список в зависимости от того, насколько велик b
. Из основной функции я бы попытался отправить [(a, 1), (b, 1) …] для создания списка, а затем отслеживать уменьшение b
здесь, пока это не будет сделано. Итак, для этой функции:
pairingL :: [(Integer, Integer)] -> [Integer] -> [Integer]
pairingL ((a,b):xs) l -- = if b /= 0 then [a,b-1] else []
| null xs = if b == 1 then [a] l else if b > 1 then [a] l pairingL [(a,b-1)] l else l
| otherwise =
if b /= 0 then [a] l pairingL ((a,b-1):xs) l else pairingL xs l
pairingL [(9,1), (7,2), (5,1)]
[9,7,7,5]
pairingL [(1,1), (2,1), (3,1)]
[1,2,3]
pairingL [(1,2), (2,2), (3,2)]
[1,1,2,2,3,3]
Я пытался разархивировать список и работать с ним, итерацией и повторением, но я не могу понять, как заставить функцию многократно просматривать список и обновлять список новыми b
значениями, а затем снова запускать.
В заключение, то, что я пытаюсь сделать, это что-то вроде:
turnIntList [(9,3),(5,1),(2,1)]
[[9,5,2],[9],[9]]
turnIntList [(1,1),(2,1),(3,1),(4,1)]
[[1,2,3,4]]
turnIntList [(1,2),(2,2),(3,2)]
[[1,2,3],[1,2,3]]
turnIntList [(4,2),(6,1)]
[[4,6],[4]]
Процесс:
Я беру первый элемент из кортежей, добавляю их в список, затем вычитаю второй элемент на 1. После выполнения этого для каждого кортежа в списке я повторяю процесс до тех пор, пока все вторые элементы для каждого кортежа не будут равны 0
Важные примечания: опять же, в списке кортежей [(a,b)], a
ВСЕГДА будет УНИКАЛЬНОЕ число от 0 до 9, и b >= 0
Комментарии:
1. У вас есть для нас другие примеры?
2. @Elmex80s Извините, я должен был привести более 1 примера. Я добавил еще несколько и более четко объяснил процесс
3. Спасибо. Ввода-вывода достаточно. Первый шаг в цикле может отвлекать
4. Для вашего развлечения,
turnIntList = transpose . map (uncurry (flip replicate))
тоже работает, хотя технически с подписью,[(a, Int)] -> [[a]]
используяInt
вместоInteger
.5. Или даже короче,
turnIntList = (>>= uncurry (flip replicate))
.
Ответ №1:
Это может
turnIntList :: [(Integer, Integer)] -> [[Integer]]
turnIntList [] = [] -- if it doesn’t compile use [[]]
turnIntList ls = [i | (i, _) <- ls] : turnIntList [(i, n - 1) | (i, n) <- ls, n - 1 > 0]
Комментарии:
1. Я знал, что должно быть более простое решение с пониманием списка. Я довольно новичок в Haskell, и это одна из областей, в которых я все еще довольно слаб. Обязательно прочитаю об этом подробнее. Одна вещь, которую я не понимаю, я бы предположил, что это вызовет ошибку
n
не в области видимости, поскольку она нигде явно не объявлена, однако это работает отлично.2.
n
связан соответствием шаблону понимания внутреннего списка @WilliamJones