Одновременная сортировка (C #)? - PullRequest
0 голосов
/ 05 января 2012

У меня есть список частот слов, который содержит строки, упорядоченные в алфавитном порядке, и несортированные целые числа, которые представляют частоту слов (нет необходимости читать текст или что-то еще, потому что запрос «(буква) (число)» набирается пользователь в консоли). Мне не нужно считать их или что-то в этом роде, а печатать наиболее часто встречающиеся слова при каждом конкретном вводе, например, в консоли, например: «AA 12». В этом случае он начинался с «A», поэтому идеальным вариантом будет поиск наиболее частого startWith("A") по меньшей мере с 5 словами в порядке убывания, относящихся к его частоте, но в то же время с порядком A-Z.

Я прочитал много материалов о книгах BST, Dictionary, Tuple, SortedList, List, SortedSet, Linq ... и алгоритмах, и я узнал, что ключи и значения можно сортировать по возрастанию, убыванию, AZ, но не в одновременно ... Кто-то может объяснить мне, как я могу ввести этот запрос "AA 12", в котором я уже разбил строку a = "AA"; и int b = 12; в BST или бинарное дерево поиска строки, в виде частоты слова int, но без необходимости считать, просто применить запрос, который извлекает 5 наиболее часто встречающихся слов, соответствующих строке и целому числу из этого 100000 слов частотного списка и консольной печати это как автозаполнение поиска Google, но более простой?

образец списка частот 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 слов, так что ... Я хочу сейчас узнать, как я могу улучшить свои лямбды, чтобы получить 15 секунд 1000 запрос списка частот или что я могу сделать, если лямбды не будут работать?

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



    }

}

}

Ответы [ 2 ]

1 голос
/ 05 января 2012

Хочешь что-нибудь подобное?

    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))

Если бы я только хотел топ 5.

0 голосов
/ 06 января 2012

Я думаю, что вы можете настроить OrderBy для достижения ваших требований поиска. Давайте кратко рассмотрим:

Ваш ввод:

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

Желаемый результат поиска "AA"

AAA
AA
AABB
AAB

Итак, AAA предшествует AA, потому что у него более высокая частота, но AABB идет после, потому что AABB < 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 займет немного больше памяти, но вы должны делать это только один раз вместо каждого фильтра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...