Print all unique elements in the array/list
Здравейте, днес попаднах на следната задача:
Print all unique elements in an array.
input:
1 2 3 4 5 5 5 6
output:
1 2 3 4 6
Запознах се с Distinct(), но с него принтирам само това "1 2 3 4 5 6". Има ли някакъв друг подобен метод, с които да кажа, че искам числата да се запишат в нов лист, но само ако не се повтарят, потретват и пр. в първоначалния лист? И разбира се кода да е разбираем за човек, който е на ниво Fundamental, защото всички решения, които прегледах досега в stackoverflow бяха напълно неразбираеми. :)
Все пак мисля, че успях да измисля някакво решение само с Destinct плюс още един допълнителен for цикъл. Понеже нямам Judge за тази задача не съм сигурна дали не би се счупила програмата с някой инпут. И вече установих, че при инпут 1 1 2 2 6, принтирам 2 6, вместо само 6.
using System;
using System.Collections.Generic;
using System.Linq;
namespace W3resourceArrayExe
{
class MainClass
{
public static void Main(string[] args)
{
Console.Write("Input the number of elements to be stored in the first array: ");
int input = int.Parse(Console.ReadLine());
Console.WriteLine($"Input {input} elements in the array:");
var firstList = new List<string>();
for (int i = 0; i < input; i++)
{
Console.Write($"element-{i} : ");
string num = Console.ReadLine();
firstList.Add(num);
}
var newListDestinct = firstList.Distinct().ToList();
for (int i = 0; i < newListDestinct.Count; i++)
{
int counter = -1;
for (int k = 0; k < firstList.Count; k++)
{
if (newListDestinct[i] == firstList[k])
{
counter++;
}
if (counter > 0)
{
newListDestinct.RemoveAt(i);
break;
}
}
}
Console.WriteLine(string.Join(" ",newListDestinct));
}
}
}
Здравей @krum_43,
благодаря за включването. :)
Може би аз не съм задала достатъчно ясно условието.
При инпут: "1 1 1 2 3 4" аз искам само 2 3 4, т.е ако даден елемент от първоначалния лист се повтаря, потретва и пр. аз не искам да го принтирам във втория лист, защото той не е уникален по условие.
Случайно все още написания с молив лист А4 с инпутите и аутпутите на тази задача стой на бюрото ми. :)
инпут-----аутпут
1 1 1 2 3 4--- 2 3 4
2 3 4 1 1 1--- 2 3 4
2 3 1 1 1 4---- 2 3 4
2 1 3 1 1 4---- 2 3 4
1 2 1 1 3 4---- 2 3 4
2 1 1 3 1 4----- 2 3 4
2 1 1 3 4 1---- 2 3 4
1 1 1 2 2 2 3 4--- 3 4
1 1 1 3 4 2 2 2---- 3 4
3 4 1 1 1 2 2 2---- 3 4
3 1 1 1 2 2 4 2---- 3 4
3 1 1 1 2 2 2 4---- 3 4
1 1 1 2 2 2 3 4---- 3 4
1 1 2 3 2 4 1 1---- 3 4
Здравей @Drakojan,
да, при повторно тестване разбрах, че не връщам for цикъла от 0. И преди няколко дена коригирах кода си (втория ми пост) и работи коректно, поне с въпросните инпути. Но благодаря за забележката, тъкмо вече се надявам,че ще го имам предвид още преди тестването. :)
Поздрави!
Да,така е.
Забелязах грешката още вчера,но ме домързя да я корегирам.
Ето ти един код,който принтира само уникалните елементи:
https://pastebin.com/tiGcXTKw
Като вариант може и така :)
static void Main( )
{
List<int> numbers = Console.ReadLine().Split().Select(int.Parse)
.GroupBy(x => x)
.Where(x => x.Count() == 1)
.Select(x => x.Key)
.ToList();
Console.WriteLine(string.Join(" ", numbers));
}
Hello nickwork,
Твоите решения както обикновено са най-кратки и интересни.
Би ли пояснил защо ти е нужен този ред от кода ти,при условие че става въпрос за елементи на списък?
Select(x => x.Key) ?!?
Привет, това го правя за да взема само ключа на групата...groupby групира всички еднакви елементи в групи, като всяка група има ключ и елементи (все едно keyvaluepair)...използвам селект за да взема само ключа на групата, която отговаря на условието, което съм задал в where клаузата...ако не използвам селект колекцията ще остане под формата на групи и ще трябва да мисля други магии за да отпечатам само ключевете им (в случая селекта е идеален за тази цел, без него мисля, че ще се получи все едно лист от масиви ако след where веднага извикаш to list)...
List<int> numbers = Console.ReadLine().Split().Select(int.Parse)
.GroupBy(x => x) // групира всички еднакви елементи в групи
.Where(x => x.Count() == 1) // филтрира да останат групите, където броят на елементите в тях е равен на 1 (ако е повече от 1 значи не са уникални...)
.Select(x => x.Key) // взима само ключа на групата (самите елементи вече не са ни нужни)
.ToList(); // прави лист от уникалните ключове
Благодаря Ви за двете решение! :)
Ако нямате нищо против, пак ще изкоментирам най-краткото решение, че да съм сигурна, че не пропускам нещо.
Ако имаме масива 2 3 2 3 4 5 8
.GroupBy(x => x) -- ще групира елементите в няколко масива с едно и също число , т.е "2 2", "3 3", "4", "5" ,"8" или са групирани, но са си в един и същи масив?
.Where(x => x.Count() == 1) -- ще вземе само тези с един елемент "4", "5", "8";
.Select(x => x.Key) -- ще махне елементите от масивите, които са заделени за тях и ще направи възможно принтирането им самостоятелно?
Каква е разликата между "ключ" и "елементи"? Пазят се в отделни памети ли-едното като масив, а другото като прост тип? Защо когато се опитам да изтрия ".Select(x => x.Key) " от целия код, изобщо кода не работи?
Структурата на GroupBy е <TKey,TElement>. , като TElement представлява колекция от елементи. Тази структура доста прилича на речник, в случая бихме използвали Dictionary<int, List<int>>. Ако имаме масива 2 3 2 3 4 5 8, с GroupBy ще получим 5 различни групи с ключове (2, 3, 4, 5, 8), като във всяка група (под всеки ключ) ще бъдат записани като елемнти :
2: [ 2, 2 ]
3: [ 3, 3 ]
4: [ 4 ]
5: [ 5 ]
8: [ 8 ]
Най добре разгледай в дебъг режим как изглежда тази структура и смятам, че ще ти стане ясно...даже добави още числа:
IEnumerable<IGrouping<int, int>> numbers = new int[] { 2, 3, 2, 3, 4, 5, 8 }
.GroupBy(x => x);
.Where филтрира там където елементите под даден ключ са равни на 1..
За разликата между "ключ" и "елементи"...всеки ключ отговаря за определени елемнти...но по добре прегледай лекцията за... не се сещам как беше точното наименование в курса... нещо от рода речници, dictionary , асоциативни масиви.. и 3те наименования означават едно и също нещо...намери тази лекция..
И на края тези типове данни са рефентни, не се печатат без селект, защото без него се получава нещо като матрица.. като аналог все едно имаш int[] test = new int[] {1,2,3,4,5}; и викаш Console.WriteLine(test); което няма как да стане.
...Предполагам, че в момента караш фундаменталс модула, ако да, и да не успееш да разбереш как точно се случва това преобразуване не се притеснявай, на този етап е много по важно да се научиш да решаваш поставените задачи с прости фор цикли, а не с готова функционалност, като тази предоставена ни от .Linq... успех :)
Да,ясно.
Здравейте @nickwork,
вашето най-подробно обяснение предварително ми разпали голям интерес към асоциативните масиви, които ще са и следващата ми лекция във Фундаментал модула.
Мисля, че вашето кратко решение с използването на Linq вече ми се изясни. Благодаря за отделеното време!
Поздрави!