我有一个学校作业,我需要计算每个字母在文本文件中出现的次数,我不能使用字典,也不能使用LinQ,然后我需要按字母顺序排列,并按照迭代的顺序。
string = "hello world"
output =
D=1
E=1
H=1
L=3
O=2
R=1
W=1
L=3
O=2
D=1
E=1
H=1
R=1
W=1
到目前为止,我的方法只适用于字母顺序,而不适用于迭代。
public void testChar() {
string text = File.ReadAllText(@ "C:EcoleSession 2ProgBloc 4test.txt")?.ToUpper();
text = Regex.Replace(text, @ "[^a-zA-Z]", "");
List < char > listChar = new List < char > ();
foreach(char lettre in text) {
listChar.Add(lettre);
}
int countPosition = 0;
List < int > position = new List < int > ();
listOfChar.Add(listChar[0]);
listOfRepetitions.Add(1);
position.Add(countPosition);
int jumpFirstItteration = 0;
foreach(var item in listChar) {
if (jumpFirstItteration == 0) {
jumpFirstItteration++;
}
if (listOfChar.Contains(item)) {
int pos = listOfChar.IndexOf(item);
listOfRepetitions[pos] += 1;
} else if (!listOfChar.Contains(item)) {
listOfChar.Add(item);
listOfRepetitions.Add(1);
countPosition++;
position.Add(countPosition);
}
}
}
Please help:D
计算一致性的规范方法是使用整数数组来计算字母,其大小与文本中不同字母的数量相同-在这种情况下,只是普通的大写字母a - z。
然后遍历大写字母,如果它们在范围内,则增加该字母对应的计数。
为了简化,你可以做两个观察:
- 要将字母转换为索引,只需从字符代码中减去' a '。
- 要将索引转换为字母,只需在索引中添加' a '并将结果强制转换回字符。(强制类型转换是必要的,因为向char类型添加int类型的结果是int类型,而不是char类型。)
完成后,您将获得按字母顺序排列的所有字符计数。但是,您还需要按照出现频率的顺序排列字母。要计算这个值,可以使用array. sort()的重载,该重载接受两个数组:第一个参数是要排序的数组,第二个参数是要按照与第一个数组相同的方式排序的数组。
如果将计数数组作为第一个数组,并将按字母顺序计数的所有字母数组作为第二个数组(即字母A..Z),那么在对第二个数组进行排序后,将以正确的顺序为第一个数组提供要显示的字母。
把所有这些放在一起:
public void testChar()
{
string filename = @"C:EcoleSession 2ProgBloc 4test.txt";
string text = File.ReadAllText(filename).ToUpper();
int[] concordance = new int[26]; // 26 different letters of the alphabet to count.
foreach (char c in text)
{
int index = c - 'A'; // A..Z will convert to 0..25; other chars will be outside that range.
if (index >= 0 && index < 26)
++concordance[index];
}
// Display frequency in alphabetic order, omitting chars with 0 occurances.
for (int i = 0; i < concordance.Length; ++i)
{
if (concordance[i] > 0)
Console.WriteLine($"{(char)('A'+i)} = {concordance[i]}");
}
Console.WriteLine();
// For sorting by frequency we need another array of chars A..Z in alphabetical order.
char[] aToZ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
Array.Sort(concordance, aToZ);
// Display frequency in occurance order, omitting chars with 0 occurances.
for (int i = 0; i < concordance.Length; ++i)
{
if (concordance[i] > 0)
Console.WriteLine($"{aToZ[i]} = {concordance[i]}");
}
}
也许添加一些排序函数?
position.sort((a,b)=> if a < b return 1; if a > b return -1; return 0;)
这将是一个基于整数值的普通排序函数,但由于您处理的是列表,因此它变得有点乏味。
position.sort((a,b)=> if a[i] < b[i] return 1; if a[i] > b[i] return -1; return 0;)
其中I为要比较的整数的索引
原谅我,我来自java
不一定是最有效的,但可以工作。
首先,一个简单的字母类,它可以比较它的属性。
public class Letter
{
public char Symbole { get; set; }
public int Frequency { get; set; }
public int CompareLetter(object obj)
{
Letter other = obj as Letter;
if (other == null) return 1;
return this.Symbole.CompareTo(other.Symbole);
}
public int CompareFrequency(object obj)
{
Letter other = obj as Letter;
if (other == null) return 1;
return this.Frequency.CompareTo(other.Frequency);
}
}
然后是填充List of Letter
的方法public static List<Letter> ReturnLettersCount(string fileName)
{
string text;
List<Letter> letters = new List<Letter>();
using (StreamReader sr = new StreamReader(fileName))
{
text = sr.ReadToEnd().ToLower();
}
foreach (char c in text)
{
if (char.IsLetter(c))
{
Letter letter = letters.Find((letter) => letter.Symbole == c);
if (letter == null)
{
letters.Add(new Letter() { Symbole = c, Frequency = 1 });
}
else
{
letter.Frequency++;
}
}
}
return letters;
}
和用户代码
static void Main(string[] args)
{
string fileName = @"pathtoyourtextFile.txt";
List<Letter> letters = ReturnLettersCount(fileName);
letters.Sort( (a, b) => a.CompareLetter(b) );
foreach(Letter letter in letters)
{
Console.WriteLine($"{letter.Symbole}: {letter.Frequency}");
}
Console.WriteLine("--------------------------");
letters.Sort((b, a) => a.CompareFrequency(b));
foreach (Letter letter in letters)
{
Console.WriteLine($"{letter.Symbole}: {letter.Frequency}");
}
}
没有Linq和Dictionary就像步行去20英里外的杂货店。;)
//C# vs >= 8.0
using System;
using Entry = System.Collections.Generic.KeyValuePair<char, int>;
// class header ...
public static void Sort() {
var text = "hello world";
var contest = new System.Collections.Generic.List<Entry>(text.Length);
foreach (var c in text) {
if (!char.IsLetter(c)) {
continue;
}
var i = contest.FindIndex(kv => kv.Key == c);
if (i < 0) {
contest.Add(new(c, 1));
}
else {
contest[i] = new(c, contest[i].Value + 1);
}
}
contest.Sort((e1, e2) => e1.Key - e2.Key);
Console.Write("n{0}nn", string.Join('n', contest));
contest.Sort((e1, e2) => e2.Value - e1.Value);
Console.Write("n{0}nn", string.Join('n', contest));
}
一些可能会派上用场的建议。
您可以构建一个容器(这里的CharInfo
类对象),以存储您收集的关于找到的每个字符的信息,它的位置以及它在文本文件中被找到的次数。
这个类容器实现了IComparable(比较器只是将char值作为整数与另一个对象的char值进行比较)。
这使得对List<CharInfo>
进行排序变得简单,只需调用其sort()方法:
public class CharInfo : IComparable<CharInfo>
{
public CharInfo(char letter, int position) {
Character = letter;
Positions.Add(position);
}
public char Character { get; }
public int Occurrences { get; set; } = 1;
public List<int> Positions { get; } = new List<int>();
public static List<string> CharsFound { get; } = new List<string>();
public int CompareTo(CharInfo other) => this.Character - other.Character;
}
由于您可以使用Regex类,因此您可以使用Regex. matches()返回[a-zA-Z]
范围内的所有字符。每个Match对象还存储找到该字符的位置。
(注意,您可以只使用Matches集合并GroupBy()
结果,但您不能使用LINQ和其他建议将只是静音:)
循环Matches
集合,测试一个字符是否已经存在于列表中;如果是,将1
添加到Occurrences
属性中,并将其位置添加到Positions
属性中。
如果还没有,添加一个新的CharInfo
对象到集合中。该类的构造函数接受一个char和一个位置。Occurrences
属性默认为1
(您创建了一个新的CharInfo
,因为您发现了一个新的字符,它是出现n°1)。
Sort()
。Sort()
将调用类的iccomparable . compareto()方法。
string text = File.ReadAllText([File Path]);
var matches = Regex.Matches(text, @"[a-zA-Z]", RegexOptions.Multiline);
var charsInfo = new List<CharInfo>();
foreach (Match m in matches) {
int pos = CharInfo.CharsFound.IndexOf(m.Value);
if (pos >= 0) {
charsInfo[pos].Occurrences += 1;
charsInfo[pos].Positions.Add(m.Index);
}
else {
CharInfo.CharsFound.Add(m.Value);
charsInfo.Add(new CharInfo(m.Value[0], m.Index));
}
}
// Sort the List<CharInfo> using the provided comparer
charsInfo.Sort();
- 在搜索其他文本文件前先调用
CharInfo.CharsFound.Clear()
。
你可以打印结果如下:
foreach (var chInfo in charsInfo) {
Console.WriteLine(
$"Char: {chInfo.Character} " +
$"Occurrences: {chInfo.Occurrences} " +
$"Positions: {string.Join(",", chInfo.Positions)}");
}
注意,大写和小写字符被视为不同的元素。
根据需要修改