2014-09-22 4 views
1

Как говорится в названии, я пытаюсь подсчитать количество повторений значений в одном массиве. Так, например, если бы существовал массив со значениями 1, 1, 2, 2, результат выглядел бы примерно так: Значение (1) произошло (2) раза \ n Значение (2) произошло (2) раза. Вот то, что я до сих пор:Как я могу подсчитать количество повторений значений в одном массиве?

foreach (var i in anArray) 
{ 
    foreach (var m in secondArray) 
    { 
     if (i == m) 
     { 
      count++; 
     } 
    } 
    Console.WriteLine("\nValue " + i + " occurred " + count + " times"); 
} 

Я создал копию первого массива (secondArray) и пытаюсь сделать из-за сравнения массивов, но что-то не так. Вложенный цикл подсчитывает мои значения дважды. Итак, где бы он сказал: значение (1) произошло (2) раза, следующее показание говорит: значение (1) произошло (4) раз, вместо перехода к следующему значению, которое не является (1). Я понимаю, что он подсчитывает второй (1) и добавляет предыдущий счет к нему ... по крайней мере, я думаю, что понимаю. Как я могу обойти это только с помощью массивов и списков?

+0

Сложность O (N^2) немного неудачное. –

+2

Почему вы сделали второй массив? –

+0

Какова природа чисел в массиве .. могут ли они быть сколь угодно большими? они, как правило, малы - например, ниже определенного небольшого числа? могут ли числа в массиве быть -ve? Насколько велика может быть массив? нормально ли использовать дополнительную память для получения ответа? Есть ли проблема в работе алгоритма? –

ответ

2

В текущем дизайне, вы можете просто установить подсчитывать фронт:

foreach (var i in anArray) 
{ 
    count = 0; // Initialize each loop 
    foreach (var m in secondArray) 
    { 
     if (i == m) 
     { 
      count++; 
     } 
    } 
    Console.WriteLine("\nValue " + i + " occurred " + count + " times"); 
} 

Это, как говорится, можно построить словарь из второго массива, и использовать эту:

var dict = secondArray.GroupBy(v => v).ToDictionary(g => g.Key, g => g.Count()); 
foreach(var i in anArray) 
{ 
    if (dict.ContainsKey[i]) 
     Console.WriteLine("\nValue " + i + " occurred " + dict[i] + " times"); 
    else 
     Console.WriteLine("\nValue " + i + " occurred 0 times"); 
} 
+0

Похоже, это может сработать. Мне нужно вернуть код обратно, прежде чем я смогу проверить его. Я все же думаю, вместо того, чтобы просто показывать: «Значение (1) произошло (2) раза« один раз », оно перейдет к следующему (1) в массиве и снова отобразит эту строку ..., которая идет для каждого повторяющегося значения. Как я могу сделать это там, где он отображает счет один раз для каждого повторяющегося значения? – 2014-09-22 23:01:37

+2

@BenignBaboon Если 'anArray' имеет повторы, просто выполните' foreach (var i в anArray.Distinct()) {'... –

+0

Большое спасибо. Он работает, и теперь у меня есть новый инструмент в моей панели инструментов. – 2014-09-23 00:26:25

2

Вы может использовать linq

var counts = anArray.Concat(secondArray) 
    .GroupBy(x => x) 
    .Select(g => new { Number = g.Key, Count = g.Count() }); 

foreach(var c in counts) 
{ 
    Console.WriteLine("\nValue " + c.Number + " occurred " + c.Count + " times"); 
} 
1

используя группу, вы можете сделать это одним лайнером для отображения событий ...

anArray.GroupBy(a => a).ToList() 
    .ForEach(g => Console.WriteLine("Value {0} occurs {1} times", g.Key, g.Count())); 
0

Вы можете добавить System.Linq пространство имен в классе, а затем:

var result = l.GroupBy(a => a).Select(s => new {Key= s.Key ,Counter= s.Count()}); 
    foreach (var item in result) 
    Console.WriteLine("Value {0} occurred {1} times",item.Key,item.Counter); 
1

Другой вариант:

foreach (var distinctItem in anArray.Distinct()) 
{ 
    Console.WriteLine("\nValue '{0}' occurred '{1}' times.", distinctItem, 
     anArray.Count(i => i == distinctItem)); 
}