在C#列表中标记位置

时间:2015-07-06 14:28:19

标签: c# list

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

我能想到的唯一方法是循环遍历整个列表,并且还有很多if语句来查看单词的第一个字母。不是最优雅的解决方案。

有没有人知道一种简单的方法,而不是26条if语句?

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

6 个答案:

答案 0 :(得分:8)

好吧,您可以使用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));

或者更有用的是,保留第一个和最后一个索引:

Dictionary<char, Tuple<int, int>> entryMinMax = words
    .Select((value, index) => new { value, index })
    .GroupBy(pair => pair.value[0])
    .ToDictionary(g => g.Key,
                  g => Tuple.Of(g.Min(p => p.index), g.Max(p => p.index));

或者,如果要点是用第一个字母有效地对单词进行分组,那么只需使用查找:

ILookup<char, string> lookup = words.ToLookup(word => word[0]);

然后你可以使用:

char first = 'B'; // Or whatever
Random rng = new Random(); // But don't create a new one each time...
var range = lookup[first];
var count = range.Count();
if (count == 0)
{
    // No words starting with that letter!
}
int index = random.Next(count);
var randomWord = range.ElementAt(index);

答案 1 :(得分:3)

我会以不同的方式处理这个问题,并且它不需要订购它。

    public List<string> GetAllStringsStartingWith(char startsWith, List<string> allWords)
    {
        List<string> letterSpecificWords = allWords.FindAll(word => word.ToLower()[0].Equals(startsWith));
        return letterSpecificWords;
    }

从这里开始,你现在有一个列表,其中只包含以字母&#34; a&#34;开头的单词。你可以改变&#34; a&#34;用一个变量来表示你需要的变量,并且它总会找到所有以该字母开头的变量。

注意:

word.ToLower()用于确保它是小写值。如果您切换要查找变量的字母,您也希望对变量执行此操作。

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

这假定列表中没有空条目。

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

答案 2 :(得分:0)

这可能是xy问题的一个例子。 为什么你需要每个字母最后一次出现的索引吗?很可能,这不是你想做的事。

无论如何要回答您的问题,对于每封信,您都可以使用FindLastIndex方法。

int index = myList.FindLastIndex(i => i.ToLower()[0] == 'a');

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

要检索最后一次:

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

获取索引:

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

答案 5 :(得分:0)

您可以按一个周期执行此操作:

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;
}