简体   繁体   English

确定一个列表是否有偶数个元素而不计算元素的数量

[英]Decide if a list has an even number of elements without counting the number of elements

Implement the isLengthEven :: [a] -> Bool function that decides if a list contains an even number of elements.实现isLengthEven :: [a] -> Bool函数,该函数决定列表是否包含偶数个元素。 In this exercise, using the length function or any other function that returns the number of elements of a list is prohibited.在本练习中,禁止使用length函数或任何其他返回列表元素数量的函数。 Hint: All we have to check is whether we can walk the entirety of the list through two by two or does the function miss an item at the very end.提示:我们需要检查的是我们是否可以两两遍历整个列表,或者函数是否在最后遗漏了一个项目。

For example: isLengthEven "Apple" == True , isLengthEven "Even" == True , isLengthEven [] == False例如: isLengthEven "Apple" == True , isLengthEven "Even" == True , isLengthEven [] == False

So far, I tried pattern matching and recursion, which is in my opinion the optimal way of doing this exercise.到目前为止,我尝试了模式匹配和递归,在我看来,这是进行此练习的最佳方式。 My code is as follows:我的代码如下:

isLengthEven :: [a] -> Bool
isLengthEven [] = False
isLengthEven (x:[]) = False
isLengthEven (x:(y:[])) = True
isLengthEven (x:(y:(z:[]))) = False
isLengthEven (x:(y:(z:(q:[])))) = True
isLengthEven (x:xs) = isLengthEven (xs)

This returns the correct values up until I insert the fifth element into the list.这将返回正确的值,直到我将第五个元素插入列表中。 It returns True for any number of elements above or equal to 5. I suppose there's a problem with the recursion part.对于大于或等于 5 的任意数量的元素,它返回True 。我想递归部分有问题。

You need only two base cases here:您在这里只需要两个基本情况:

  1. an empty list, which has as length 0 and thus should return True ;一个列表,长度为0 ,因此应该返回True and
  2. a singleton list which contains one element and thus has an odd length.包含一个元素并因此具有奇数长度的单例列表。

The recursive cases each time move two steps forward in the list, so:递归情况每次在列表中向前移动两步,因此:

isLengthEven :: [a] -> Bool
isLengthEven [] = True
isLengthEven [x] = False
isLengthEven (_:_:xs) = isLengthEven xs

Often one defines two functions: isLengthEven and isLengthOdd and thus these functions each time call each other recursively with:通常定义两个函数: isLengthEvenisLengthOdd ,因此这些函数每次都以递归方式相互调用:

isLengthEven :: [a] -> Bool
isLengthEven [] = True
isLengthEven (_:xs) = isLengthOdd xs

isLengthOdd :: [a] -> Bool
isLengthOdd [] = False
isLengthOdd (_:xs) = isLengthEven xs

A single-stepping solution单步解决方案

Note that the excellent answer by Willem is already an optimized one.请注意, Willem的优秀答案已经是优化的答案

If you prefer a straight unoptimized version and choose to disregard the hint, you can do with just the first and last clauses of your initial code.如果您更喜欢未经优化的直接版本并选择忽略提示,则可以仅使用初始代码的第一个和最后一个子句。 Like this:像这样:

-- warning: the following is incorect, needs changes:
isLengthEven :: [a] -> Bool
isLengthEven [] = False
isLengthEven (x:xs) = isLengthEven (xs)

Both clauses are incorrect, but it is easy to fix them:这两个子句都不正确,但很容易修复它们:

isLengthEven :: [a] -> Bool
isLengthEven [] = True
isLengthEven (x:xs) = not (isLengthEven xs)

and taken together, these two clauses cover all possible situations.综合起来,这两个条款涵盖了所有可能的情况。

As is, this function uses a lot of stack space for long inputs.照原样,此函数为长输入使用了大量堆栈空间。 This can be fixed thru the common argument-as-accumulator trick.这可以通过常见的参数作为累加器技巧来解决。 Here:这里:

isLengthEven :: [a] -> Bool
isLengthEven xs = go True xs  where
    go b   []    =  b
    go b (x:xs)  =  go (not b) xs

where the go auxiliary stepping function is tail-recursive.其中go辅助步进函数是尾递归的。

With that change, my machine is getting 67% of the performance of the obvious but prohibited (even (length xs)) solution.通过这种变化,我的机器获得了明显但被禁止(even (length xs))解决方案的 67% 的性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用JQuery计算嵌套元素的数量 - Counting number of nested elements with JQuery 我怎样才能将数字打印为列表的元素而不用引号和方括号呢? - How can I print the number as elements of a list without the quotes and square brackets should be their? 转换一定数量的元素 - transformation a certain number of elements 在大量元素中显示哪个四分位数代表数据的函数 - Function to show which quartile number belong data in a large list of elements 如何从列表中按列号删除元素? - How can I remove elements by columns number from a list? 递归 function 返回列表中直接后跟该元素的两倍的元素数 - Recursive function to return the number of elements in a list that are followed directly by double that element 为多个列表创建一个 function 并正确分组列表元素 - Create a function for a number of lists and correctly group the list elements 有没有办法删除链表中超过一定数量的某些元素? - Is there a way to delete certain elements in a linked list above a certain number? 使用列表元素的定义来决定给出最小答案的元素 - Using definition on elements of a list to decide which give smallest answer 如何在不使用 splat 运算符的情况下解压缩具有不同数量元素的元组? - How do i unpack tuple with different number of elements without using splat operator?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM