同时排序(C#)

本文关键字:排序 | 更新日期: 2023-09-27 18:19:27

我有一个单词频率列表,其中包含按字母顺序排列的字符串和未排序的int,这些字符串表示单词的频率(不需要读取txt或其他内容,因为用户在控制台中键入了"(字母)(数字)"查询)。我不需要计算它们或类似的东西,而是通过控制台中的每个特定输入来打印最频繁的单词,例如:"AA 12"。在这种情况下,它以"A"开头,因此理想的做法是检索最频繁的startWith("A"),其中至少有5个单词按降序与其频率相关,但同时具有A-Z顺序。

我读过很多关于BST、Dictionary、Tuple、SortedList、List、SortedSet、Linq。。。和算法书籍,我了解到键和值可以按升序、降序、A-Z排序,但不能同时排序。。。有人可以解释我如何引入"AA 12"的查询,其中我已经拆分为字符串a="AA";并且int b=12;进入字符串的BST或二进制搜索树,int词频风格,但不需要计数,只需应用一个查询,检索与字符串和这个100000词频列表的int匹配的5个最频繁的单词,并像谷歌搜索自动完成一样控制台打印它,但更基本?

样本词频A-Z列表:

AA 12
AAA 32
AAB 4
AABB 38
BBAA 3
CDDDA 76
...
YZZZ 45
ZZZZZY 356

用户查询:"AA 15"

理想答案:

AAA
AA
AABB
AAB

代码:

 var list = new List<KeyValuePair<string, int>>();
 StreamReader sr = new StreamReader("C:''dicti.txt");
 while (true)
 {
      string line = sr.ReadLine();   //read each line
      string[] ln;
      if (line == null) break;            // no more lines
      try
      {
           ln = line.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);
           string a = ln[0];
           int b = Convert.ToInt32(ln[1]);
           list.Add(new KeyValuePair<string, int>(a, b));       
      }
      catch (IndexOutOfRangeException)
      {
           break;
      }
      string word = Console.ReadLine();
      string[] ln2;
      ln2 = word.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);
      string am = ln2[0];
      int bm = Convert.ToInt32(ln2[1]);

这是我迄今为止编写的代码。我有点不知道如何根据用户查询的第一个字母按字母顺序和频率对值进行排序。

<小时>

这是我实际版本的代码。。。我有1:15分钟的时间阅读完整的1000个单词的频率列表,所以……我现在想知道我该如何改进我的lambdas,以获得15秒1000个单词频率列表的要求,或者如果lambdas不起作用,我该怎么办??

    static void Main(string[] args)
    {
        var dic = new Dictionary<string, int>();

        int contador = 0;
        StreamReader sr = new StreamReader("C:''dicti.txt");
        while (true)
        {
            string line = sr.ReadLine();   // To read lines
            string[] ln;
            if (line == null) break;            // There is no more lines
            try
            {
                ln = line.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);
                string a = ln[0];
                int b = Convert.ToInt32(ln[1]);
                dic.Add(a,b);   
            }
            catch (IndexOutOfRangeException) { break; }
        }
        string[] ln2;
        string am,word;
        int bm;
        do
        {
            //counter++;
            do
            {
                word = Console.ReadLine();

                ln2 = word.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries);
                    am = ln2[0];
                    bm = Convert.ToInt32(ln2[1]);
            } while (!(am.Length >= 2 && bm >= 1 && bm <= 1000000 )); 
            if (true)
            {
                var aj = (dic.Where(x => x.Value >= bm).Where(x => x.Key.StartsWith(am)).OrderByDescending(d => d.Value).Take(2));

                foreach (var p in aj)
                {

                        Console.WriteLine("{0} ", p.Key);

                }
            }
        } while (counter < 1001);

    }
}

}

同时排序(C#)

你想要这样的东西吗?

    public static IEnumerable<KeyValuePair<string, int>> SearchAndSortBy(Dictionary<string, int> fullSet, string searchFilter)
    {
        return fullSet.Where((pair) => pair.Key.Contains(searchFilter)).OrderByDescending((pair) => pair.Value);
    }

然后你这样使用它:

        var mySet = new Dictionary<string, int>();
        mySet.Add("AA", 12);
        mySet.Add("AAA", 32);
        mySet.Add("AAB", 4);
        mySet.Add("AABB", 38);
        mySet.Add("BBAA", 3);
        mySet.Add("CDDDA", 76);
        //...
        mySet.Add("YZZZ", 45);
        mySet.Add("ZZZZZY", 356);
        var results = SearchAndSortBy(mySet, "AA");
        foreach (var item in results)
        {
            Console.Write(item.Key);
            Console.Write(" ");
            Console.WriteLine(item.Value);
        }

当我运行它时,我会得到以下结果:

AABB 38
AAA 32
AA 12
AAB 4
BBAA 3

我甚至可以将for循环更改为:

    foreach (var item in results.Take(5))

如果我只想进入前五名。

我认为您可以调整OrderBy以满足您的搜索要求。让我们快速看一下:

您的输入:

AA 12
AAA 32
AAB 4
AABB 38
BBAA 3
CDDDA 76

搜索"AA"所需的结果

AAA
AA
AABB
AAB

所以AAAAA之前是因为它具有更高的频率,而AABBAABB < AAA之后。现在问题来了:它也是AA < AAA,所以如果你按字母顺序排序,那么无论频率如何,AA都会出现在AAA之前。

但是,如果你用最后一个字符"继续"每个单词,那么你就可以通过先按字母顺序排序,然后按频率排序得到你想要的:

public static IEnumerable<KeyValuePair<string, int>> FilterAndSort(IEnumerable<KeyValuePair<string, int>> fullSet, string searchFilter, int maxKeyLength)
{
    return fullSet
            .Where(p => p.Key.StartsWith(searchFilter))
            .OrderBy(p => p.Key.PadRight(maxKeyLength, p.Key.Last()))
            .ThenByDescending(p => p.Value);
}

测试:

List<KeyValuePair<string, int>> list = new List<KeyValuePair<string,int>>
{
    new KeyValuePair<string, int>("AA", 12),
    new KeyValuePair<string, int>("AAA", 32),
    new KeyValuePair<string, int>("AAB", 4),
    new KeyValuePair<string, int>("AABB", 38),
    new KeyValuePair<string, int>("BBAA", 3),
    new KeyValuePair<string, int>("CDDDA", 76),
};
foreach (var p in FilterAndSort(list, "AA", list.Max(p => p.Key.Length)))
{
    Console.WriteLine("{0} {1}", p.Key, p.Value);
} 

输出:

AAA 32
AA 12
AABB 38
AAB 4

您可以在阅读列表时通过预计算填充词来优化它。在这种情况下,您可能想要使用Tuple<string, string, int>(原始单词、填充单词、频率)。而不是KeyValuePair会占用更多的内存,但你必须在每个过滤器上只做一次。