有没有办法仅在连续的情况下才能在列表中找到两个字符的序列?

Is there a way to find if a sequence of two chars are found in a list only if they are consecutive?

我目前正在使用 elm 语法。一个例子是这样的:

(序列 ('a') ('b')) ('c') ['a', 'b', 'c', 'd'] 。在这个例子中,我只测试元素 'a'、'b'、'c' 是否是列表的成员。如果是,那么我将它分区并获得 (['a','b','c'],['d'])

在以下情况下遇到问题

 (Sequence ('a') ('b')) ('c') ['a', 'b', 'c', 'a']

获取结果: (['a','b','c','a'],[])

我的问题是:我应该放置什么条件,以便元素'a'和'b'必须连续避免单独匹配的情况?

下面是一些测试元素序列是否出现在列表中的代码:

module Main exposing (main)
 
import Html exposing (Html, text)


containsSeq : List a -> List a -> Bool
containsSeq seq list =
    let
        helper remainingSeq remainingList savedSeq savedList =
            case remainingSeq of
                [] ->
                    True

                x :: xs ->
                    case remainingList of
                        [] ->
                            False

                        y :: ys ->
                            if x == y then
                                helper xs ys (savedSeq ++ [ x ]) (savedList ++ [ y ])

                            else
                                case savedList of
                                    [] ->
                                        helper (savedSeq ++ remainingSeq) ys [] []

                                    y2 :: y2s ->
                                        helper (savedSeq ++ remainingSeq) (y2s ++ remainingList) [] []
    in
    helper seq list [] []


main =
    text <| Debug.toString <| containsSeq [ 'a', 'b', 'c' ] [ 'a', 'b', 'a', 'b', 'c', 'd' ]

这只检查序列是否出现并且元素的类型必须是 comparable

上面的函数更改为 return 将旧列表分区为 3 个元素的元组,其中包含 (elementsBefore, sequence, elementsAfter)。结果被包裹在 Maybe 中,这样如果找不到序列,它会 returns Nothing.

module Main exposing (main)

import Html exposing (Html, text)


partitionBySeq : List a -> List a -> Maybe ( List a, List a, List a )
partitionBySeq seq list =
    let
        helper remainingSeq remainingList savedSeq savedCurrentList savedOldList =
            case remainingSeq of
                [] ->
                    Just ( savedOldList, seq, remainingList )

                x :: xs ->
                    case remainingList of
                        [] ->
                            Nothing

                        y :: ys ->
                            if x == y then
                                helper xs ys (savedSeq ++ [ x ]) (savedCurrentList ++ [ y ]) savedOldList

                            else
                                case savedCurrentList of
                                    [] ->
                                        helper (savedSeq ++ remainingSeq) ys [] [] (savedOldList ++ [ y ])

                                    y2 :: y2s ->
                                        helper (savedSeq ++ remainingSeq) (y2s ++ remainingList) [] [] (savedOldList ++ [ y ])
    in
    helper seq list [] [] []


main =
    text <| Debug.toString <| partitionBySeq [ 'a', 'b', 'c' ] [ 'a', 'b', 'a', 'b', 'c', 'd' ]

当然,如果你只处理字符,你不妨将列表转换为String,使用String.fromList,第一个版本使用String.contains "abc" "ababcd"String.split "abc" "ababcd" 实施第二个。

此答案假定如果您有 Sequence 'a' 'b' 'c' 并根据列表 ['a', 'b', 'c', 'a'] 对其进行测试,您希望收到结果 (['a', 'b', 'c'], ['a'])(如 中所述) .

在pseudo-code中:

  1. 将列表分成两部分,list1list2list1 的长度应与您的序列相同。 Elm 为
  2. 提供 List.take and List.drop
  3. 使用辅助函数
  4. 将序列转换为列表list_sequence
  5. 测试 list1list_sequence 是否相等
  6. 如果是,return 元组 (list1, list2)

下面是实际的 Elm 代码: https://ellie-app.com/bjBLns4dKkra1