2015-09-24 3 views
1

Я пишу программу, которая принимает значения пользовательских данных 1-10 и сохраняет их в массиве. Я пытаюсь выяснить, как добавить счетчик, который позволит мне выводить, сколько раз вводилось каждое число и сколько неверных чисел было введено.C# Добавить счетчик для каждого числа в цикле

class Program 
{ 
    static void Main(string[] args) 
    { 
     int[] data = GetData(); 
    } 

    private static int[] GetData() 
    { 
     int[] dataArray = new int[100]; 
     int n = 0; 
     int intValue = 0; 

     while (true) 
     { 
      Console.WriteLine("Enter a number 0-10 (Q to end)"); 
      string lineValue = Console.ReadLine(); 

      if (lineValue.ToLower().Trim().Equals("q")) 
      { 
       break; 
      } 

      if (!int.TryParse(lineValue, out intValue)) 
      { 
       Console.WriteLine("INVALID DATA - Try again."); 
       continue; 
      } 

      if (intValue < 0 || intValue > 10) 
      { 
       Console.WriteLine("NUMERIC DATA OUT OF RANGE - Try again."); 
       continue; 
      } 

      dataArray[++n] = intValue; 
      dataArray[0] = n; 
     } 
     return dataArray; 
    } 
} 
+0

Я предполагаю, что downvotes есть, потому что вы должны выглядеть довольно трудно для фактического вопроса. Если вы отредактируете вопрос, чтобы уточнить, с чем именно вы столкнулись, надеюсь, что они либо вернут downvotes (или, возможно, даже вверх). – Kritner

ответ

1

Вы можете сделать это:

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     // note updated to use a list rather than array (just preference) 
     List<int> data = GetData();   
    } 

    private static List<int> GetData() 
    { 
     List<int> list = new List<int>(); 
     int intValue = 0; 
     int invalidAttempts = 0; // added to keep track of invalid values 

     while (true) 
     { 
      Console.WriteLine("Enter a number 0-10 (Q to end)"); 
      string lineValue = Console.ReadLine(); 

      if (lineValue.ToLower().Trim().Equals("q")) 
      { 
       break; 
      } 

      if (!int.TryParse(lineValue, out intValue)) 
      { 
       Console.WriteLine("INVALID DATA - Try again."); 
       invalidAttempts++; 
       continue; 
      } 

      if (intValue < 0 || intValue > 10) 
      { 
       Console.WriteLine("NUMERIC DATA OUT OF RANGE - Try again."); 
       invalidAttempts++; 
       continue; 
      } 

      list.Add(intValue); 
     } 

     Console.WriteLine("Invalid attempts {0}", invalidAttempts); 

     // this is using linq to group by the individual numbers (keys), 
     // then creates an anon object for each key value and the number of times it occurs. 
     // Create new anon object numbersAndCounts 
     var numbersAndCounts = list 
      // groups by the individual numbers in the list 
      .GroupBy(gb => gb) 
      // selects into a new anon object consisting of a "Number" and "Count" property 
      .Select(s => new { 
       Number = s.Key, 
       Count = s.Count() 
      }); 

     foreach (var item in numbersAndCounts) 
     { 
      Console.WriteLine("{0} occurred {1} times", item.Number, item.Count); 
     } 

     return list; 
    } 
} 

примечание Я использую list, а не array, я найти их легче работать.

Работа демо:

https://dotnetfiddle.net/KFz1UY

Можно ли сделать вывод пойти в числовом порядке? Сейчас он просто отображает все номера, которые были напечатаны первыми. Например, 1, 7, 7, 4 будет 1: 1 7: 2 4: 1, как я могу изменить это, чтобы идти 1: 1 4: 1 7: 2?

Sure возможен!Ниже (и обновленный оригинальный демо)

Я только что изменил:

var numbersAndCounts = list 
     .GroupBy(gb => gb) 
     .Select(s => new { 
      Number = s.Key, 
      Count = s.Count() 
     }); 

к:

var numbersAndCounts = list 
     .GroupBy(gb => gb) 
     .Select(s => new { 
      Number = s.Key, 
      Count = s.Count() 
     }) 
     .OrderBy(ob => ob.Number); 
+0

Спасибо. Это работает именно так, как я хотел, но я не слишком хорошо знаком с используемой техникой linq. – ChaCol

+0

LINQ поражает, если вы незнакомы. Вот начало работы: https://msdn.microsoft.com/en-us/library/bb397933.aspx – Kritner

+0

Можно ли сделать вывод в числовом порядке? Сейчас он просто отображает все номера, которые были напечатаны первыми. Например, 1, 7, 7, 4 будет 1: 1 7: 2 4: 1, как я могу изменить это, чтобы идти 1: 1 4: 1 7: 2? – ChaCol

1

У вас уже есть пример счетчика (n), который вы можете использовать в качестве примера для записи количества недопустимых входов. Просто увеличить его в этом, если блок:

if (intValue < 0 || intValue > 10) 
     { 
      Console.WriteLine("NUMERIC DATA OUT OF RANGE - Try again."); 
      myInvalidCounter ++; 
      continue; 
     } 

Чтобы получить количество каждого введенного номера - вы можете анализировать данные, хранящиеся в вашем DataArray.

EDIT: Я только что заметил, у вас есть два примера недостоверных данных - плохая исходные данные и из данных диапазона - вам необходимо установить счетчики в зависимости от обстоятельств - может быть, по одному или совместно один и т.д.

2

Вы могли бы установите счетчик перед состоянием while для недопустимых номеров.

int invalidNumbersCounter = 0; 

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

if (!int.TryParse(lineValue, out intValue)) 
{ 
    Console.WriteLine("INVALID DATA - Try again."); 
    invalidNumbersCounter++; 
    continue; 
} 

Что касается другого вопроса, сколько раз каждое число, вы могли бы просто использовать простой LINQ, чтобы сделать трюк ,

static void Main(string[] args) 
{ 
    int[] data = GetData(); 

    var statistics = data.GroupBy(x=>x) 
         .Select(gr => new 
         { 
          Number = gr.key, 
          Times = gr.Count() 
         }); 

    foreach(var statistic in statistics) 
    { 
     Console.WriteLine(String.Format("The number {0} found {1} times in you array", statistic.Number, statistic.Times)); 
    } 
} 

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

Update

Для того, мы избегаем подсчитывать значения, которые не были введены пользователем, и по существу являются начальными значениями массива, мы могли бы инициализировать значение массива -1, когда это мы создаем массив, как показано ниже:

int[] dataArray = Enumerable.Repeat(-1, 100).ToArray(); 

Затем мы должны обновить наш Linq запрос к следующему:

var statistics = data.Skip(1) 
         .Where(number => number!=-1) 
         .GroupBy(x=>x) 
         .Select(gr => new 
         { 
          Number = gr.key, 
          Times = gr.Count() 
         }); 
+0

Существует проблема с пустыми слотами, которые будут также учтены (я бы добавил «Где раньше, чем GroupBy, чтобы удалить их»). Но об этом я и думал. (А также значение в данных [0] должно быть исключено подсчетом) – Steve

+0

Привет, Стив и спасибо за ваш комментарий. У меня есть один вопрос. Поскольку 'data', будет массив целых чисел, где будут пустые слоты? Есть определенно то, что я не поймал правильно. – Christos

+1

@ Christos Я угадываю, потому что он инициализировал свой массив 'int' равным 100. Если вы вводите только 2 числа в то время, тогда в массиве будет 98 отдельных 0s? – Kritner

Смежные вопросы