There are two lists

var lst1 = new List<string>(){"1","2","3"}; var lst2 = new List<string>(){"4","2","3"}; 

With Intersect I display those elements that are repeated, but I would like to know how many times each element repeats.

 var rez = lst1.Intersect(lst2); // Ρ‚ΡƒΡ‚ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ 2 ΠΈ 3 

And I would like so

 var rez = lst1.Method(lst2) 

2 occurs 2 times 3 occurs 2 times.

  • In the intersection, in theory, 2 and 3 occur once. If you need 2 times, maybe we are talking about the union? - VladD

1 answer 1

Apparently, you need something like this:

 var l1 = new[] { "ΠΊΠΎΡ‚ΠΈΠΊ", "ΠΊΠΎΡ‚ΠΈΠΊ", "слоник", "Π·Π°ΠΉΡ‡ΠΈΠΊ", "Π‘Π°Ρ€ΠΌΠ°Π»Π΅ΠΉ" }; var mostOften = l1.GroupBy(s => s) // сгруппировали ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ строки .OrderByDescending(g => g.Count()) // отсортировали ΠΏΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρƒ Π³Ρ€ΡƒΠΏΠΏΡ‹ .First() // самый большой Ρ€Π°Π·ΠΌΠ΅Ρ€ Ρƒ ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΡ‹ .First(); // Π±Π΅Ρ€Ρ‘ΠΌ ΠΈΠ· Π½Π΅Ρ‘ любой элСмСнт (ΠΎΠ½ΠΈ всС ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅) Console.WriteLine(mostOften); 

(gives the ΠΊΠΎΡ‚ΠΈΠΊ ).

If you need the most frequent in the two lists, just concatenate them: l1.Concat(l2).GroupBy(...


Update

If you need the most common element in the intersection, everything is not so simple. Intersect collapses replays in lists. Therefore, the correct way, apparently, is:

 var l1 = new[] { "Π·Π°ΠΉΡ‡ΠΈΠΊ", "ΠΊΠΎΡ‚ΠΈΠΊ", "ΠΊΠΎΡ‚ΠΈΠΊ", "слоник", "Π·Π°ΠΉΡ‡ΠΈΠΊ", "Π‘Π°Ρ€ΠΌΠ°Π»Π΅ΠΉ", "Π·Π°ΠΉΡ‡ΠΈΠΊ" }; var l2 = new[] { "ΠΊΠΎΡ‚ΠΈΠΊ", "ΠΊΠΎΡ‚ΠΈΠΊ", "слоник", "Π·Π°ΠΉΡ‡ΠΈΠΊ", "Π‘Π°Ρ€ΠΌΠ°Π»Π΅ΠΉ", "Ρ‘ΠΆΠΈΠΊ" }; // считаСм, сколько Ρ€Π°Π· ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· элСмСнтов ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ список var firstCount = l1.GroupBy(s => s) // Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΡƒΠ΅ΠΌ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ .ToDictionary(g => g.Key, g => g.Count()); var result = // Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΡƒΠ΅ΠΌ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ l2.GroupBy(s => s) // Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ количСство .Select(g => new { Value = g.First(), SecondCount = g.Count() }) // ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ Ρ‚Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π½Π΅Ρ‚ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ спискС .Where(vc => firstCount.ContainsKey(vc.Value)) // замСняСм количСство Π½Π° ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΈΠ· этого ΠΈ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅Π³ΠΎ списков .Select(vc => new { vc.Value, Count = Math.Min(vc.SecondCount, firstCount[vc.Value]) }) // сортируСм ΠΏΠΎ ΡƒΠ±Ρ‹Π²Π°Π½ΠΈΡŽ .OrderByDescending(vc => vc.Count) // ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт - с самым большим Count .First() // Π±Π΅Ρ€Ρ‘ΠΌ ΠΈΠ· Π½Π΅Π³ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ .Value; Console.WriteLine(result); 

( ΠΊΠΎΡ‚ΠΈΠΊ again)


Update

More elegant solution (suitable for the modified condition):

 var lookup1 = l1.ToLookup(s => s); var lookup2 = l2.ToLookup(s => s); var result = l1.Intersect(l2) .ToDictionary(v => v, v => Math.Min(lookup1[v].Count(), lookup2[v].Count())); foreach (var kv in result) { Console.WriteLine($"Item {kv.Key} occurs {kv.Value} times"); } 
  • And why not group + group join? - Pavel Mayorov
  • @PavelMayorov: It is possible and so, but this is your decision. Write! - VladD