Механизм перебора всех возможных вариантов слов в определенной фразе.

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 094
Благодарностей
128
Баллы
63
Есть ключевые фразы с количеством запросов, например:

баскетбольный мяч коричневый |100
мяч коричневый баскетбольный|80
коричневый баскетбольный мяч |120
и т.д.

Хочу найти эту правильную фразу с самым большим количеством запросов, а остальные удалить.
Где-то, наверняка, есть готовый механизм перебора всех возможных вариантов слов в определенной фразе.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Хочу найти эту правильную фразу с самым большим количеством запросов, а остальные удалить.
Если строки лежат в списке, то разбиваем на две части - фраза и кол-во запросов, разделитель |.
Дальше сортируем по убыванию, по кол-ву запросов, и берем фразу.
Ну и очищаем список.
C#:
var list = project.Lists["какой то список"]
var phrase = list
   .Select(f =>
   {
     var split = f.Split('|');
     return new Tuple<string, int>(split[0].Trim(), int.Parse(split[1].Trim()));
   })
   .OrderByDescending(f => f.Item2)
   .First()
   .Item1;
list.Clear();
 
  • Спасибо
Реакции: bizzon

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 094
Благодарностей
128
Баллы
63
Moadip, спасибо, тут, наверное, другая сложность - это то, что сначала нужно
брать эти фразы из списка подряд
потом искать эти "идентичные" фразы из перестановленных слов, а дальше уже удалять с наименьшим числом запросов, тем самым оставляя "правильные" с точки зрения лексики.

Я бы мог попробовать сделать это на кубиках, но мне нужен снипет перебора слов из фразы.
1. делит фразу на слова
2. составляет все возможные варианты словосочетаний из этих перестановленных слов.

А дальше уже ваш механизм сортировки и удаления по наименьшим запросам.
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 625
Благодарностей
4 611
Баллы
113
здесь не нужно все комбинации генерировать. Достаточно в имеющихся все слова по алфавиту расставить
 

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 094
Благодарностей
128
Баллы
63
здесь не нужно все комбинации генерировать. Достаточно в имеющихся все слова по алфавиту расставить
doc, прости, туплю.

Т.е вообще все фразы в списке изменяет на "по алфавитные",
потом удаляются идентичные с наименьшим запросом,
а как дальше вернуть эту "правильную" фразу к изначальному порядку слов?

баскетбольный мяч коричневый |100
мяч коричневый баскетбольный|80
коричневый баскетбольный мяч |120

"правильная"
коричневый баскетбольный мяч |120
 

doc

Client
Регистрация
30.03.2012
Сообщения
8 625
Благодарностей
4 611
Баллы
113
doc, прости, туплю.

Т.е вообще все фразы в списке изменяет на "по алфавитные",
потом удаляются идентичные с наименьшим запросом,
а как дальше вернуть эту "правильную" фразу к изначальному порядку слов?

баскетбольный мяч коричневый |100
мяч коричневый баскетбольный|80
коричневый баскетбольный мяч |120

"правильная"
коричневый баскетбольный мяч |120
правильную нужно тоже оставлять в записи, например, третьим полем
 
  • Спасибо
Реакции: bizzon

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 094
Благодарностей
128
Баллы
63
Спасибо, буду думать.
Есть шанс на кубиках собрать.
 

Moadip

Client
Регистрация
26.09.2015
Сообщения
509
Благодарностей
823
Баллы
93
Берем кажду строку, разбиваем, разделитель |.
Потом фразу разбиваем, разделитель пробел.
Сортируем слова и соединяем, получаем "ключ", типа "баскетбольныйкоричневыймяч".
В временный список пихаем объекты типа Tuple<string, string> ключ и оригинальная строчка.
Дальше группируем по ключу.
Ну а потом как выше выбираем "правильную" фразу из группы.
В итоге в output будет "коричневый баскетбольный мяч" и "серый шерстянной свитер".

C#:
var list = new List<string>
{
   "баскетбольный мяч коричневый |100",
   "мяч коричневый баскетбольный|80",
   "коричневый баскетбольный мяч |120",
   "серый шерстянной свитер | 150",
   "шерстянной серый свитер | 120",
   "свитер серый шерстянной | 80",
};

var temp = new List<Tuple<string, string>>();
var output = new List<string>();

foreach (var line in list)
{
   var str = string.Join("", line.Split('|')[0].Trim().Split(' ').OrderBy(s => s).ToList());
   temp.Add(new Tuple<string, string>(str, line));
}

foreach (var group in temp.GroupBy(g => g.Item1))
{
   var phrase = group
     .Select(f =>
     {
       var split = f.Item2.Split('|');
       return new Tuple<string, int>(split[0].Trim(), int.Parse(split[1].Trim()));
     })
     .OrderByDescending(f => f.Item2)
     .First()
     .Item1;

   output.Add(phrase);
}
 
  • Спасибо
Реакции: wdunyushkin и bizzon

doc

Client
Регистрация
30.03.2012
Сообщения
8 625
Благодарностей
4 611
Баллы
113
Стало интересно, в общем немного linq)
C#:
var list = new List<string>
{
   "баскетбольный мяч коричневый |100",
   "мяч коричневый баскетбольный|80",
   "коричневый баскетбольный мяч |120",
   "серый шерстянной свитер | 150",
   "шерстянной серый свитер | 120",
   "свитер серый шерстянной | 80",
};

list = list.Select(x=>string.Join("", x.Split('|')[0].Trim().Split(' ').OrderBy(s => s))+"@"+x)
    .OrderBy(x=>x.Split('@')[0])
    .ThenBy(x=>int.Parse(x.Split('|')[1].Trim()))
    .GroupBy(x=>x.Split('@')[0])
    .Select(x=>x.Last())
    .Select(x=>x.Split('@')[1].Trim()).ToList();

return string.Join("\r\n", list);
 
  • Спасибо
Реакции: wdunyushkin и bizzon

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 094
Благодарностей
128
Баллы
63
Дорогие, вот это фантастика, огромное спасибо!!!
 
  • Спасибо
Реакции: wdunyushkin

wdunyushkin

Client
Регистрация
10.07.2020
Сообщения
5
Благодарностей
7
Баллы
3
Всем привет, возникла у меня задача перебором разных вариантов выявить строку с наименьшим числом.
Взял за основу код от doc, но т.к. я в C# не разбираюсь, решил сперва методом тыка (а кто не без греха), по типу замени знак > на < и т.п., ясень пень ничего не вышло.

Понял что так ничего не выйдет полез читать про первый метод в коде OrderBy узнал что это сортировка, и решил поменять сортировку списка
OrderBy: упорядочивает элементы по возрастанию
OrderByDescending: упорядочивает элементы по убыванию
поменял значит сортировку иии... все тоже самое, странно (почему не поменялась сортировка?).

Понял что харош лениться и полез читать про все методы и в целом про LINQ.
Мне помогли статьи:

и понял что вместо последнего элемента последовательности нужно взять первый элемент последовательности
Вот код если кому нужно:
C#:
var list = new List<string>
{
   "рощ15 рыл5 кир17 рощ15 |59",
   "рощ15 кир17 рыл5 рощ15 |64",
   "рощ15 кир17 рыл5 рощ15 |43",
   "рощ15 кир17 рыл5 рощ15 |28",
};

list = list.Select(x=>string.Join("", x.Split('|')[0].Trim().Split(' ').OrderBy(s => s))+"@"+x)
    .OrderBy(x=>x.Split('@')[0])
    .ThenBy(x=>int.Parse(x.Split('|')[1].Trim()))
    .GroupBy(x=>x.Split('@')[0])
    .Select(x=>x.First())
    .Select(x=>x.Split('@')[1].Trim()).ToList();

return string.Join("\r\n", list);
 
  • Спасибо
Реакции: djaga и bizzon

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)