如何在Haskell中查找字符串中字符的频率?

时间:2011-08-18 13:55:26

标签: haskell

如何计算字符串中字符的频率,然后以表的形式输出它们?

例如,如果我输入单词“happy”,结果将是

h 1  
a 1  
p 2  
y 1  

如果可以按ASCII顺序排序,那就太棒了。

我知道我需要使用count函数,任何其他提示都会受到赞赏。

编辑:所有的答案都很棒,只有我是Haskell的初学者,我实际上并不了解他们在做什么。

7 个答案:

答案 0 :(得分:40)

最简单的解决方案是使用Data.Map存储从字符到频率的中间映射。然后,您可以使用fromListWith轻松构建计数。由于Data.Map已排序,因此您可以免费以ASCII顺序获取它们。

λ> :m + Data.Map
λ> let input = "happy"
λ> toList $ fromListWith (+) [(c, 1) | c <- input]
[('a',1),('h',1),('p',2),('y',1)]

那么这里发生了什么?

我们的想法是使用字符作为键并将频率作为值来构建Data.Map(树形图)。

首先,我们获取输入字符串并使用1生成每个字符的元组以指示一次出现。

λ> [(c, 1) | c <- input]
[('h',1),('a',1),('p',1),('p',1),('y',1)]

接下来,我们使用fromListWith通过将每个键值对重复插入到地图中,从这些键值对构建有序映射。我们还给它一个函数,当一个键已经在地图中时将使用它。在我们的例子中,我们使用(+),这样当多次看到一个字符时,我们会将计数添加到现有的总和中。

最后,我们使用toList将地图转换回键值元组列表。

答案 1 :(得分:10)

可能会有更短的内容,但这有效:

Prelude> import Data.List
Prelude Data.List> map (\x -> (head x, length x)) $ group $ sort "happy"
[('h',1),('a',1),('p',2),('y',1)]

答案 2 :(得分:4)

func xs = map (\a -> (head a, length a)) $ group $ sort xs

答案 3 :(得分:3)

使用列表理解,无需任何导入或排序。

[ (x,c) | x<-['A'..'z'], let c = (length.filter (==x)) "happy", c>0 ]

结果:

[('a',1),('h',1),('p',2),('y',1)]

上面是来自:

的过滤和重写(只有字数> 0的字符)
[(x,(length.filter (==x)) "happy" ) | x<-['A'..'z']]

说明:

  • 列出与给定角色(A..z)匹配的所有字符。
  • 对于每个字符,请计算此列表(==长度)
  • 将此计数放入带有字符
  • 的元组中

答案 4 :(得分:0)

我将逐步解决问题。使用标准功能可以实现更短的解决方案。

您想要一个排序结果,因此

result = sort cs
    where

cs 将是一个元组列表,其中第一个元素是字符,第二个元素是它出现的次数。

        cs = counts "happy"
        counts [] = []
        counts (c:cs) = (c, length otherc + 1) : counts nonc where
             (otherc, nonc) = partition (c==) cs

就是这样。

有趣的是,计数适用于支持==运算符的任何项目列表。

答案 5 :(得分:0)

import Data.Array (Ix, accumArray, assocs)

eltDist :: (Bounded a, Ix a, Eq b, Num b) => [a] -> [(a, b)]
eltDist str = filter ((/=0) . snd ) $ 
     assocs (accumArray (+) 0 (minBound, maxBound) [(i, 1) | i <- str])

“minBound”和“maxBound”将取决于i推断的类型范围。对于 Char ,它将是0 - 1,114,111,这是奢侈但不是不可能的。如果你计算Unicode字符会特别方便。如果您只对ASCII字符串感兴趣,那么(0,255)就可以了。关于数组的一个好处是它们可以被任何可以映射到整数的类型索引。见 Ix

assocs将索引和数组从数组中拉出到一个对列表中,并过滤掉未使用的数组。

答案 6 :(得分:-1)

//Count the frequency of character in a string 

package waytocreateobject;
import java.util.Scanner;
public class Freqchara {

    public static void main(String[] args) {

        int c = 0, x = 0, loop = 26, space = 0;
        int count[] = new int[loop];
        //Arrays.fill(count, x);
        Scanner sc = new Scanner(System.in);
        String str =sc.nextLine();
        char[] charr = str.toCharArray();
        int aa = str.length();
        //System.out.println(str.charAt(10));
        //System.out.println(str.charAt(11));
        for (int mm = 0; mm < aa; mm++) {
            if (str.charAt(c) != '\0') {    //Considering characters from 'a' to 'z' only and ignoring others.
                if ((str.charAt(c) >= 'a') && (str.charAt(c) <= 'z')) {
                    x = (int) str.charAt(c) - (int) 'a';
                    // System.out.println(x);
                    count[x] = count[x] + 1;
                }
                c++;
            } else {}
        }

        // printing all the charcter
        int i = 97;
        for (int j = 0; j < loop; j++) {
            char ch = (char) (i + j);
            System.out.println(ch + "  occurs  " + count[j] + " times in the string");
        }
        System.out.println("  occurs " + space);
    }
}