空列表问题的头函数

时间:2017-12-18 14:40:29

标签: list haskell filter

我想在地图中使用'head'功能。 问题是'head'函数只接受非空列表。 我有清单列表:

function reqKeysToFunc( keySet, myFunc) {
    var pressedKeys = {};

    document.onkeydown = function(event) {
        "use strict";
        var myKey = event.key.toUpperCase();
        //var keySet = 'ZM';  //remove this line - keySet is defined as an argument
        if (keySet.search(myKey) > -1 ) {
            pressedKeys[myKey] = true;
            document.onkeydown = null;

            if(pressedKeys.entries().filter((key, val) => val).length === keySet.length) {
                myFunc();
            }
        }
    }
}

function tmp() {
    alert('hello');
}

reqKeysToFunc('ZM', tmp);

我需要迭代列表列表两次

let ll =[["dog", "cat"], ["pig", "cow"], []]

我想知道我是否可以迭代列表列表一次,或者在没有'过滤器'的情况下在地图中添加“if condition”

任何建议都将不胜感激。

1 个答案:

答案 0 :(得分:8)

是的,实际上您可以将其编写为 list comprehension 语句,并使用模式匹配

result = [ h | (h:_) <- ll ]

或作为一种功能:

heads :: [[a]] -> [a]
heads ll = [ h | (h:_) <- ll ]

所以我们在这里使用匹配所有非空列表的模式(h:_),我们直接获取此列表的头h并将其添加到列表中。如果在列表推导中使用模式(在左箭头<-的左侧),它将跳过与模式不匹配的元素。

这比使用length更安全 ,因为如果使用无限列表,length将陷入无限循环。此外,通过使用非总计head函数的模式,我们有更多语法保证此函数可以工作(是的,一旦非空元素被过滤,我们当然可以肯定head不会导致错误,但我们只知道这一点,因为我们有head函数的信息。

请注意,您的尝试将导致语法错误,因为您使用if,而没有thenelse部分。

或者,我们可以像@DanielWagner所说的那样,以不同方式编写heads函数,例如使用:

heads :: [[a]] -> [a]
heads ll = concatMap (take 1) ll

或使用列表monad的 bind

heads :: [[a]] -> [a]
heads = (take 1 =<<)

或者我们可以转置2d列表。在这种情况下,第一行包含列表的所有头部。但由于不能保证有这样的行,我们可以在末尾添加一个空列表,如:

heads :: [[a]] -> [a]
heads = head . (++ [[]]) . transpose