如何计算字符串中字符的频率,然后以表的形式输出它们?
例如,如果我输入单词“happy”,结果将是
h 1
a 1
p 2
y 1
如果可以按ASCII顺序排序,那就太棒了。
我知道我需要使用count函数,任何其他提示都会受到赞赏。
编辑:所有的答案都很棒,只有我是Haskell的初学者,我实际上并不了解他们在做什么。
答案 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']]
说明:
答案 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);
}
}