Понимание списка Haskell и `группа`

#list #haskell #grouping #list-comprehension #higher-order-functions

#Список #haskell #группировка #понимание списка #функции более высокого порядка

Вопрос:

ввод:

funcA [((0,’x’),1),((0,’ у’),3),((1,’ у’),3),((1,’ z’),3),((2,’ x’),2),((2, ‘y’),2)]

вывод

[(0, 1, «x»), (0, 3, «y»), (1, 3, «yz»), (2, 2, «xy»)]

Я пытаюсь сгруппировать, начав узел и конечный узел, а затем concat все имена ребер (такие значения, как 'x' , 'y' …). Таким образом, порядок вывода [(start, end, "concat val"), ...]

Как я могу написать funcA на языке Haskell??

Я попробовал groupBy , понимание списка, map функцию в нем, но не смог понять это.

Комментарии:

1. Из чего следует выводить funcA [((0,'a'),0),((1,'b'),1),((0,'c'),0)] ? Мне интересно, всегда ли значения, которые необходимо сгруппировать, находятся рядом во входном списке.

2. Я да, верно, поэтому мне нужно сначала отсортировать его

Ответ №1:

Вы могли бы определить funcA как:

 import Data.Function (on)
import Data.List (groupBy)

funcA :: Eq a => [((a,b),a)] -> [(a,a,[b])]
funcA =
  map (s@(((x,y),_):_) -> (x, y, map snd s))
  . groupBy ((==) `on` fst)
  . map (((x,v),y) -> ((x,y),v))
  

Учитывая список: [((0,'x'),1),((0,'y'),3),((1,'y'),3),((1,'z'),3),((2,'x'),2),((2,'y'),2)]

  • map В конце цепочки координаты объединяются в кортеж:

    [((0,1),'x'),((0,3),'y'),((1,3),'y'),((1,3),'z'),((2,2),'x'),((2,2),'y')]

  • groupBy Группы по координатам:

    [[((0,1),'x')],[((0,3),'y')],[((1,3),'y'),((1,3),'z')],[((2,2),'x'),((2,2),'y')]]

  • Первый map объединяет символы с той же координатой в строки с этой координатой.

Комментарии:

1. map ( s@(((x,y),_):_) -> (x, y, map snd s)) тоже должно выполнить эту работу.

2. (главное, что меня раздражало, это нули (0,0,[]) . во всяком случае, undefined следовало использовать s . но, конечно, как написано, этот fold просто повторно реализует map .)

3. @WillNess: Спасибо за отзыв. Вы правы (0,0,[]) , это некрасиво. Ваше предложение использовать map snd etc. намного лучше. Я обновил соответствующим образом.

4. … и теперь он может работать с любым Eq типом, а не только Int с or (Num,Eq) . 🙂

5. @WillNess: Спасибо, я тоже это сделал. 🙂