С# Простое консольное приложение, отображающее/логическую проблему

        List<int> numberList = new List<int>();
        List<int> uniqueList = new List<int>();

        string input;
        int number = 0;
        bool over = false;

        while (!over)
        {
            input = Console.ReadLine();
            if (input == "quit")
            {
                over = true;
                break;
            }
            if (int.TryParse(input, out number))
            {
                numberList.Add(number);
            }
        }

        for (int i = 0; i < numberList.Count; i++)
        {
            if (!uniqueList.Contains(number))
            {
                uniqueList.Add(number);
            }
        }

        for (int i = 0; i < uniqueList.Count; i++)
        {
            Console.WriteLine(uniqueList[i]);
        }

        Console.ReadKey();

Привет! Мне нужна помощь с этой программой, которая принимает числа, но после ввода "quit" она должна вывести список всех введенных уникальных номеров.

Например, вот ввод: 5, 5, 5, 2, 2, 1, 3 В консоли должны отображаться только 1 и 3, потому что они являются единственными уникальными номерами.

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

Не могли бы вы сказать мне, почему? Что мне нужно сделать, чтобы перечислить их все?


person lapartman    schedule 28.08.2018    source источник
comment
Когда вы выполняли отладку, что делал код такого, чего вы не ожидали?   -  person mjwills    schedule 28.08.2018
comment
Ваш код просто игнорирует дубликаты, он не сохраняет числа, на которые ссылаются только один. Для этого: numberList.GroupBy(number => number).Where(group => (group.Count() == 1)).Select(group => group.Key). Кроме того, использование Contains со списком очень неэффективно. Вы можете использовать Dictionary<int, int> для хранения чисел вместе с их количеством вхождений.   -  person vc 74    schedule 28.08.2018


Ответы (4)


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

    Dictionary<int, int> numberDictionary = new Dictionary<int, int>();

    string input;
    int number = 0;
    bool over = false;

    while (!over)
    {
        input = Console.ReadLine();
        if (input == "quit")
        {
            over = true;
            break;
        }
        if (int.TryParse(input, out number))
        {
            if (numberDictionary.TryGetValue(number), out int count)
            {
                numberDictionary[number] = count + 1;
            }
            else
            {
                numberDictionary.Add(number, 1);
            } 
        }
    }

    foreach(var item in numberDictionary)
    {
        if (item.Value == 1)
        Console.WriteLine(item.Key);
    }

    Console.ReadKey();
person ste-fu    schedule 28.08.2018
comment
Удалите двойной поиск в numberDictionary, и вы получите мой голос. - person vc 74; 28.08.2018
comment
Спасибо, это мой любимый ответ. Ответ выше вашего тоже работает, я просто еще не знаю LINQ, но однажды я использовал Dictionary в курсе Unity. Так мне это более понятно. - person lapartman; 28.08.2018
comment
Теперь можно получить ;) - person vc 74; 29.08.2018

Вы можете сделать это намного проще

List<int> numbers = new List<int>{1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 6, 6, 6};
var unique = numbers.Where(n => numbers.Count(m => m == n) == 1);
foreach(var u in unique)
    WriteLine(u);

Отпечатки

1

5

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

Затем он проверяет, равно ли количество вхождений n 1. Если это так, это должно быть уникальным.

Итак, для первого числа в нашем списке 1 следующее:

numbers.Count(m => m == n)

Вернется 1.

Когда n равно 2, тогда

numbers.Count(m => m == n)

Вернется 2.

person Stuart    schedule 28.08.2018
comment
Спасибо, это сработало, хотя я не понимаю часть LINQ. - person lapartman; 28.08.2018
comment
Этот код выполняет n*n сравнений, что может привести к проблемам с производительностью, если список будет расти. - person vc 74; 28.08.2018

Это полная реализация решения:

using System;
using System.Collections.Generic;
using System.Linq;

namespace EntryPoint.Concole
{
    class Program
    {
        static void Main(string[] args)
        {
           List<int> numberList = new List<int>();
           List<int> uniqueList = new List<int>();

           string input;
           int number = 0;
           bool over = false;

           while (!over)
           {
               input = Console.ReadLine();
               if (input == "quit")
               {
                  over = true;
                  break;
               }
               if (int.TryParse(input, out number))
               {
                  numberList.Add(number);
               }
           }

           var numbersDistinct = numberList.GroupBy(i => i);

           foreach (var num in numbersDistinct)
           {
              if (num.Count() == 1)
              {
                  uniqueList.Add(num.Key);
              }
           }

           for (int i = 0; i < uniqueList.Count; i++)
           {
              Console.WriteLine(uniqueList[i]);
           }

           Console.ReadKey();
        }
    }
person Smaiil    schedule 28.08.2018

Я проверил и исправил ваш код. Хотя это не идеально, но я указал на критические ошибки.

        List<int> numberList = new List<int>();
        List<int> uniqueList = new List<int>();

        string input;
        int number = 0;
        bool over = false;

        while (!over)
        {
            input = Console.ReadLine();
            if (input == "quit")
            {
                over = true;
                //break; // it is not needed since you have over = true
            }
            if (int.TryParse(input, out number))
            {
                numberList.Add(number);
            }
        }

        for (int i = 0; i < numberList.Count; i++)
        {
            //if (!uniqueList.Contains(number)) // this is the wrong line
            if (numberList.Count(q => q == numberList[i]) == 1)
            {
                //uniqueList.Add(number); // this is also wrong
                uniqueList.Add(numberList[i]);
            }
        }

        for (int i = 0; i < uniqueList.Count; i++)
        {
            Console.WriteLine(uniqueList[i]);
        }

        Console.ReadKey();

Проще говоря, метод Count(...) в

numberList.Count(q => q == numberList[i]) == 1

строка просто подсчитывает элементы numberList, которые удовлетворяют заданному условию. В этом случае условие q == numberList[i], что в основном означает подсчет элементов, равных numberList[i].

Вы также можете прочитать о делегатах и ​​лямбда-выражениях в C# для лучшего понимания.

person Unknown User    schedule 28.08.2018
comment
Спасибо, забыл убрать break. Не могли бы объяснить строку LINQ? Я не использовал их раньше, и я хотел бы понять это. - person lapartman; 28.08.2018