在C#列表中标记位置

在C#列表中标记位置,c#,list,C#,List,我有一个从字典文件中读取的字符串列表(按字母顺序排序)。我想为每个起始字母的最后一个位置创建一个索引,因此如果有1000个以A开头的单词,它将被记录为位置999(因为数组从0开始)。1000个以B开头的单词意味着B的结束位置是1999年,以此类推。这些位置值将存储在int数组中 我能想到的唯一方法是循环浏览整个列表,并用许多其他if语句查看单词的第一个字母。这不是最优雅的解决方案 有人知道一种简单的方法来实现这一点,而不是26条if语句吗 编辑:其目的是生成随机单词。如果我想要一个以B开头的单词

我有一个从字典文件中读取的字符串列表(按字母顺序排序)。我想为每个起始字母的最后一个位置创建一个索引,因此如果有1000个以A开头的单词,它将被记录为位置999(因为数组从0开始)。1000个以B开头的单词意味着B的结束位置是1999年,以此类推。这些位置值将存储在int数组中

我能想到的唯一方法是循环浏览整个列表,并用许多其他if语句查看单词的第一个字母。这不是最优雅的解决方案

有人知道一种简单的方法来实现这一点,而不是26条if语句吗


编辑:其目的是生成随机单词。如果我想要一个以B开头的单词,我会在1000到1999之间生成一个随机数,然后从列表中的那个位置获取该单词。

我会用另一种方式处理它,它不需要排序

    public List<string> GetAllStringsStartingWith(char startsWith, List<string> allWords)
    {
        List<string> letterSpecificWords = allWords.FindAll(word => word.ToLower()[0].Equals(startsWith));
        return letterSpecificWords;
    }
public List GetAllStringsStartingWith(char startsWith,List allWords)
{
列出letterSpecificWords=allWords.FindAll(word=>word.ToLower()[0]。等于(startsWith));
返回特定单词;
}
从这里你可以看到一个列表,其中只包含以字母“a”开头的单词。你可以用一个变量把“a”改成你需要的任何形式,它总是会发现所有的变量都是从这个字母开始的

注:

ToLower()用于确保它是小写值。如果您将要查找的字母切换为变量,那么您也需要对变量执行此操作

您仍然需要处理随机整数,但现在可以使用准确的计数(words.count)

这假定列表中没有空条目


words.ToLower()[0]获取第一个字符

您可以使用LINQ创建字典:

// Note: assumes no empty words
Dictionary<char, int> lastEntries = words
    .Select((index, value) => new { index, value })
    .GroupBy(pair => pair.value[0])
    .ToDictionary(g => g.Key, g => g.Max(p => p.index));

这可能是xy问题的一种情况。为什么需要每个字母最后一次出现的索引?很可能,这不是你真正想做的

无论如何,为了回答你的问题,对于每封信,你可以使用这个方法


不过,我更喜欢Jon Skeet的方法,因为您不必循环遍历每个字母。

您可以使用for循环遍历列表,并将当前元素的第一个字母与下一个元素的第一个字母进行比较。如果字母相同,则继续循环;如果字母不同,则存储下一个元素的索引,然后继续循环。

要检索最后一个:

words.LastOrDefault(i => i[0].ToLower() == 'a');
要获取索引,请执行以下操作:

words.FindLastIndex(i => i[0].ToLower() == 'a');

您可以在每个周期执行此操作:

public Dictionary<char, int> GetCharIndex(IList<string> words)
{
    if (words == null || !words.Any()) throw new ArgumentException("words can't be null or empty");
    Dictionary<char, int> charIndex = new Dictionary<char, int>();
    char prevLetter = words[0][0];
    for(int i = 1;i < words.Count;i++)
    {
        char letter = words[i][0];
        if (letter != prevLetter) //change of first letter of the word -> add previous letter to dictionary
        {
            charIndex.Add(prevLetter, i - 1);
            prevLetter = letter;
        }
    }
    charIndex.Add(words[words.Count - 1][0], words.Count - 1); //special case for last word
    return charIndex;
}
公共词典GetCharIndex(IList单词)
{
如果(words==null | |!words.Any())抛出新的ArgumentException(“words不能为null或空”);
字典charIndex=新字典();
字符/字母=单词[0][0];
for(int i=1;i将上一个字母添加到词典中
{
charIndex.Add(前一封信,i-1);
字母=字母;
}
}
charIndex.Add(words[words.Count-1][0],words.Count-1);//最后一个单词的特殊情况
返回charIndex;
}

这是一个更好的主意,我可以为每次搜索创建一个临时列表。谢谢请注意,这样做会导致性能略有下降。只要你没有100多万个条目,就不会有什么不同。你为什么不把随机化单词所需的字母作为一个参数,并将其中的字符作为变量@mike159放入equals中呢?请确保你的列表名是正确的。它不应从主列表中删除任何内容。还要注意我刚刚做的更新。此方法应始终返回以“startsWith”字符开头的单词子列表。函数明确声明它是字符是有用的。我在原始代码(derp)中使用了一个字符串。谢谢代码的第一部分给出了以下错误:无法对“int”类型的表达式应用带[]的索引@Mike159:抱歉,参数是错误的。我会修好的。
int index = myList.FindLastIndex(i => i.ToLower()[0] == 'a');
words.LastOrDefault(i => i[0].ToLower() == 'a');
words.FindLastIndex(i => i[0].ToLower() == 'a');
public Dictionary<char, int> GetCharIndex(IList<string> words)
{
    if (words == null || !words.Any()) throw new ArgumentException("words can't be null or empty");
    Dictionary<char, int> charIndex = new Dictionary<char, int>();
    char prevLetter = words[0][0];
    for(int i = 1;i < words.Count;i++)
    {
        char letter = words[i][0];
        if (letter != prevLetter) //change of first letter of the word -> add previous letter to dictionary
        {
            charIndex.Add(prevLetter, i - 1);
            prevLetter = letter;
        }
    }
    charIndex.Add(words[words.Count - 1][0], words.Count - 1); //special case for last word
    return charIndex;
}