C# skapa en lista och sortera den

Permalänk
Medlem

C# skapa en lista och sortera den

Finns det något smidigt sätt att sortera två listor med varandra?
ska sortera en List<int> och en List<String>
dessa listor innehåller information om namn och ålder för ressenärer till en reseort.

Men när jag sorterar dom så mister t.ex. names[1] sin ålder och får en annans age[i]...

Exempel:

Lisa 12
Erik 25
Oskar 38
Elinda 16

Då får Lisa 12 Erik 16 Oskar 25 och Elinda 38.

Dom ska INTE kunna byta namn, jag vill att dom ska fortfarande ha samma namn men hamna på andra placeringar i listan.

Följande kod är vad som skapar och som sorterar och skriver ut:

static void Travel() { Console.Write("Welcome to OSD Travels. How many you are? "); List<string> names = new List<string>(); List<int> point = new List<int>(); Console.ForegroundColor = ConsoleColor.Yellow; int amount = int.Parse(Console.ReadLine()); Console.ForegroundColor = ConsoleColor.Gray; for (int i = 0; i < amount; i++) { Console.Write("Namn på person " + (i + 1) + " :"); string name = Console.ReadLine(); Console.Write("Poäng för spelare " + (name) + ":"); int points = int.Parse(Console.ReadLine()); names.Add(name); point.Add(points); } point.Sort(); Console.WriteLine("\n\nNi har nu beställt biljetter för: "); for (int i = 0; i < amount; i++) { Console.WriteLine("- " + names[i] + " " + point[i]); } Console.WriteLine("Ha en trevlig resa och välkommen åter."); Console.Write("Ni har nu loggats, var god avsluta genom att trycka valfri tangent."); Console.ReadKey(); }

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk

Kika lite på KeyValuePair<string, int>: http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx
Eller så kör du bara en Dictionary<string, int>
Om inte annat kan du ju skapa en klass som heter person där du implementerar IComparable.

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Gör om dina listor till en SortedList http://msdn.microsoft.com/en-us/library/system.collections.so...
Lagra siffran som key och du behöver inte sortera listan eftersom den sätter in objekten på sin plats direkt.
Du får då en lista med KeyValuePair som Kurre nämner.

Permalänk
Medlem

Okej jag antar att skapa en helt ny klass är enklast i detta fall... Men prövar båda två ^^ Tack för snabba svar btw
Jag har jobbat med C# i 2 år nu men inte behövt skappa något sådant förrut så det är skönt med
lite utmaning!

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk
Medlem

det råcker nog med en structg egentligen eller vad hade du tänkt att klassen ska innehålla?

Visa signatur

Laptop - MacBook 2.0GHz, 4GB ram, Intel GMA 950
Stationär - i5 3570k @ 4ghz, 8gb ram, 120gb ssd + 2tb hdd, Windows 8 64bit, fractal design arc
Citera så jag hittar tillbaka :)

Permalänk
Medlem
Skrivet av freddyfresh:

Okej jag antar att skapa en helt ny klass är enklast i detta fall... Men prövar båda två ^^ Tack för snabba svar btw
Jag har jobbat med C# i 2 år nu men inte behövt skappa något sådant förrut så det är skönt med
lite utmaning!

Ursäkta, men har du jobbat med c# i två år och aldrig hållit på med listor och sortering????

Visa signatur

EPoX 8RDA+, XP2500+, 2x256Mb PC3200 (DualCh), Club3D 9800PRO, Seagate 7200.7 160Gb 8Mb Limited edition

Permalänk
Medlem

Jag var på god väg att lära mig mycket om just console application men jag struntade i det och hoppade över på grafisk programmering (windows application)....

jag är inte stolt över att jag inte tränat på listor eller sortering förr men jag tar igen det nu istället.
Och jag har fortfarande ingen aning hur jag ska sortera min sortedlist...
Min output ser nästan ut som förrut med ett undantag.. att den inte är sorterad över huvudtaget.
När jag skriver ut min sortedlist använder jag följande kod:

//Sorted är min sortedlist (SortedList<string, int> sorted = new SortedList<string, int>();) foreach (var pair in sorted) { Console.WriteLine("-Player: " + pair.Key + " Value: " + pair.Value); }

Jag vill att det ska stå sorterat enligt högsta först (alltså en slag av funktion som kontrollerar vilken av i sortedlist med högst pair.value... måste jag skapa ett index för att kontrollera det?) sedan vandrades mot högsta
Exempel:
Lina 12
Oskar 22
Farfar 67
Gammelmormor 140
osv.

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk
Medlem

Resultatet av vad jag har gjort nu på 2 timmars sökning av information om hur man gör detta har jag kommit fram till denna koden:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace utmaningFredag { class Program { public static void Main() { SortedList<string, int> sorted = new SortedList<string, int>(); Console.Write("enter a valid integer value, deciding the amount of players: "); int value = int.Parse(Console.ReadLine()); for (int i = 0; i < value; i++) { Console.Write("Player name: "); string name = Console.ReadLine(); Console.Write("enter a valid integer value of player score: "); int score = int.Parse(Console.ReadLine()); sorted.Add(name, score); Console.WriteLine("Player: " + sorted.Count() + " has been added into game."); Console.WriteLine(); } foreach (var pair in sorted) { Console.WriteLine("-Player: " + pair.Key + " Value: " + pair.Value); } Console.WriteLine("\nAmount of players added into game: " + value); Console.WriteLine("Amount of players logged in list: " + sorted.Count); Console.WriteLine("Program finished. Please finish by pressing any key."); Console.ReadKey(); } } }

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk
Hedersmedlem

Jag har knappt tittat på C# och aldrig programmerat det. Men jag kan inte se någon sortering just nu. Har du problem med koden som du har nu eller varför visar du den? Den är logisk och jag förstår den iaf.

Permalänk
Medlem

Tror inte det är listor och sortering du ska titta, tror det är objektorienterad programmering du ska läsa in dig på...

Permalänk
Medlem

Generellt så undviker jag SortedDictionary elller SortedList då prestandan är inget vidare på dom jämfört med dess "enklare" motsvarigheter, andra nackdelen kan vara att dom sorterar bara på Keys(vilket man inte alltid vill).

Jag använder nästan alltid vanlig Dictionaries eller Lists så kan du köra Lamdba expression eller Linq för att sortera den när det behovet uppstår.

Ett exempel på sortering:

list.Sort((firstPair,nextPair) => {return firstPair.Value.CompareTo(nextPair.Value); });

Visa signatur

En Laptop

Permalänk
Medlem

Pair.key ska kunna sorteras beroende på vad dess värde är, t.ex. om användaren skriver Erik och sedan 21 men om det sedan skrivs Anders 12 och efter det! Karl 31 så ska listan sortera oberoende på vad namnet är. Det ska sortera värdet på int'n som skrivits in av användaren och namnet ska följa med den string som var skriven tillsammans med den int, för när den sorterar kan erik få 12 och anders 21 och karl 31. Erik ska fortfarande ha 21 men hamna på olika ställen i sorteringen som utförs i slutändan.. där är problemet. Och jag har ingen aning på hur jag ska göra. Och dessa svar ni ger mig ligger just nu utanför min vetskap.

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk

Har ej testat denna kod men det borde gå att göra liknande:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace utmaningFredag { class Program { public static void Main() { Dictionary<string, int> sorted = new Dictionary<string, int>(); Console.Write("enter a valid integer value, deciding the amount of players: "); int value = int.Parse(Console.ReadLine()); for (int i = 0; i < value; i++) { Console.Write("Player name: "); string name = Console.ReadLine(); Console.Write("enter a valid integer value of player score: "); int score = int.Parse(Console.ReadLine()); sorted.Add(name, score); Console.WriteLine("Player: " + (i+1) + " has been added into game."); Console.WriteLine(); } foreach (var pair in sorted.OrderBy(kvp=>kvp.Value)) { Console.WriteLine("-Player: " + pair.Key + " Value: " + pair.Value); } Console.WriteLine("\nAmount of players added into game: " + value); Console.WriteLine("Amount of players logged in list: " + sorted.Count); Console.WriteLine("Program finished. Please finish by pressing any key."); Console.ReadKey(); } } }

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Ditt svar var just det jag letade efter! Tack!

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk
Medlem

freddyfrsh: Felet är att du sätter in namn som key och ålder som value. Sorted list sorterar enligt key så det är inte så konstigt det blir sorterat efter namnet

Dvs, du skulle skrivit såhär så hade det funkat:

SortedList<int, string> sorted = new SortedList<int, string>(); //... sorted.Add(score, name); //... Console.WriteLine("-Player: " + pair.Value + " Value: " + pair.Key);

jurand: Fast i just det här fallet borde väl SortedList vara snabbare?

Permalänk

@VB

Är det verkligen logiskt att åldern ska vara nyckel..? Känns ju mer logiskt att namnet ska vara nyckeln enligt mig Dock så lär ditt sätt vara snabbare än mitt

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Logiskt o logiskt.. snyggast vore väl att skapa en struct/class som innehåller ett namn o ett poäng, och jag tror inte att jag löst problemet med en sortedlist av poäng/namn om jag skulle ha det själv, men tyckte det var bra att peka ut felet så freddyfresh (och eventuellt andra som läser tråden) lär sig hur sortedlist funkar.

Permalänk
Medlem
Skrivet av vb:

jurand: Fast i just det här fallet borde väl SortedList vara snabbare?

Tja, det som är snabbare är att du slipper sortera den själv med SortedDictionary, men låt oss säga du gör X antal Insert operationer först, sorterar och sen kör select så vinner du på att använda en vanlig Dictionary.

Visa signatur

En Laptop

Permalänk
Medlem
Skrivet av vb:

freddyfrsh: Felet är att du sätter in namn som key och ålder som value. Sorted list sorterar enligt key så det är inte så konstigt det blir sorterat efter namnet

Dvs, du skulle skrivit såhär så hade det funkat:

SortedList<int, string> sorted = new SortedList<int, string>(); //... sorted.Add(score, name); //... Console.WriteLine("-Player: " + pair.Value + " Value: " + pair.Key);

jurand: Fast i just det här fallet borde väl SortedList vara snabbare?

Tack för alla snabba svar och fina tips
Det har varit till stor hjälp och jag ska pröva alla och se vilken i slutändan som blir bäst

Tack igen

Visa signatur

Citera om du vill ha svar, hjälpte jag dig, gilla svaret!
Felkod40

Permalänk
Medlem
Skrivet av jurand:

Tja, det som är snabbare är att du slipper sortera den själv med SortedDictionary, men låt oss säga du gör X antal Insert operationer först, sorterar och sen kör select så vinner du på att använda en vanlig Dictionary.

Teori:
I vårt exempelfall borde prestandan vara minst likvärdig tycker jag. I båda fallen är väl tidskomplexiteten O(n * log(n)) om vi antar att båda är gjorda på ett bra sätt?

Skulle man däremot behöva göra deletes samtidigt som man stoppar in elements skulle SortedList vara sämre, och motsvarande om man behöver ha ut listan sorterad fler än en gång, då är SortedList bättre eftersom man slipper sortera om listan.

Praktik:
Gjorde ett litet test mellan SortedList och Dictionary såhär:

static int TestSortedList() { var sl = new SortedList<int, string>(); for (int i = 0; i < names.Count; i++) { sl.Add(ages[i], names[i]); } int sum = 0; foreach (var item in sl) { sum += item.Key; } return sum; } static int TestDictionary() { var d = new Dictionary<int, string>(); for (int i = 0; i < names.Count; i++) { d.Add(ages[i], names[i]); } int sum = 0; foreach (var item in d.OrderBy(kvp => kvp.Key)) { sum += item.Key; } return sum; }

Upp till ~1000 element var SortedList snabbare, vid 10000 vann Dictionary..

Permalänk
Skrivet av vb:

Teori:
I vårt exempelfall borde prestandan vara minst likvärdig tycker jag. I båda fallen är väl tidskomplexiteten O(n * log(n)) om vi antar att båda är gjorda på ett bra sätt?

Skulle man däremot behöva göra deletes samtidigt som man stoppar in elements skulle SortedList vara sämre, och motsvarande om man behöver ha ut listan sorterad fler än en gång, då är SortedList bättre eftersom man slipper sortera om listan.

Praktik:
Gjorde ett litet test mellan SortedList och Dictionary såhär:

static int TestSortedList() { var sl = new SortedList<int, string>(); for (int i = 0; i < names.Count; i++) { sl.Add(ages[i], names[i]); } int sum = 0; foreach (var item in sl) { sum += item.Key; } return sum; } static int TestDictionary() { var d = new Dictionary<int, string>(); for (int i = 0; i < names.Count; i++) { d.Add(ages[i], names[i]); } int sum = 0; foreach (var item in d.OrderBy(kvp => kvp.Key)) { sum += item.Key; } return sum; }

Upp till ~1000 element var SortedList snabbare, vid 10000 vann Dictionary..

Intressant! Undrar vad som skulle hända rent prestandamässigt om man istället körde en klass som då implementerar IComparable? Kan testa när jag kommer hem

Skrivet av vb:

Logiskt o logiskt.. snyggast vore väl att skapa en struct/class som innehåller ett namn o ett poäng, och jag tror inte att jag löst problemet med en sortedlist av poäng/namn om jag skulle ha det själv, men tyckte det var bra att peka ut felet så freddyfresh (och eventuellt andra som läser tråden) lär sig hur sortedlist funkar.

Sant. hade nog också gjort en klass/struct. Förstår din poäng om att påvisa vad som var fel

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem
Skrivet av vb:

Tja, nu när jag såg ditt test står jag rättad av den simpla anledningen att jag yrade om SortedDictionary mot Dictionary

Det intressanta dock är att jag testade din kod med SortedList mot Dictionary och i mitt fall, vilken storlek jag än valde, vann SortedList.

Visa signatur

En Laptop

Permalänk
Medlem

Håller med Jurand och VB om att det är smidigast att vid faktiskt användning sortera/filtrera data t.ex. med hjälp av LINQ. Relativt snabbt går det också. Satte ihop ett litet test och parallel LINQ har riktigt bra prestanda. Inriktade mig på att få så jämförelsebara värden mellan test typerna som möjligt, och inte att få bästa möjliga prestande.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace Zoomware.Examples.SortedData01 { class Program { static void Main ( string [] args ) { // do a dummy restart to remove any creation penelties.. stopwatch.Restart ( ); // note: consider first iteration as a warm-up.. foreach ( var samples in new int [] { 10, 10, 100, 500, 1000, 5000, 50000, 250000, 1000000 } ) { var holder = SampleHolder.Generate ( samples ); for ( var i = 1; i <= 3; i++ ) { BenchmarkSortedList ( holder, i ); BenchmarkListWithObject ( holder, i ); BenchmarkDictionary ( holder, i ); // parallel orderby with .NET 4.0 BenchmarkListWithObjectAndPLinq ( holder, i ); } } } static void BenchmarkSortedList ( SampleHolder holder, int iteration ) { var list = new SortedList<int,string> ( holder.Samples.Count ); stopwatch.Restart ( ); foreach ( var sample in holder.Samples ) list.Add ( sample.Key, sample.Value ); var dummy = 0; foreach ( var sample in list ) dummy += sample.Key; var elapsed = stopwatch.Elapsed; Console.WriteLine ( "#{0} SortedList took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]", iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy ); } static void BenchmarkListWithObject ( SampleHolder holder, int iteration ) { var list = new List<KeyValuePair<int, string>> ( holder.Samples.Count ); stopwatch.Restart ( ); foreach ( var sample in holder.Samples ) list.Add ( new KeyValuePair<int,string> ( sample.Key, sample.Value ) ); var dummy = 0; foreach ( var sample in list.OrderBy ( kv => kv.Key ) ) dummy += sample.Key; var elapsed = stopwatch.Elapsed; Console.WriteLine ( "#{0} List with class took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]", iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy ); } static void BenchmarkListWithObjectAndPLinq ( SampleHolder holder, int iteration ) { var list = new List<KeyValuePair<int, string>> ( holder.Samples.Count ); stopwatch.Restart ( ); foreach ( var sample in holder.Samples ) list.Add ( new KeyValuePair<int, string> ( sample.Key, sample.Value ) ); var dummy = 0; foreach ( var sample in list.AsParallel().OrderBy ( kv => kv.Key ) ) dummy += sample.Key; var elapsed = stopwatch.Elapsed; Console.WriteLine ( "#{0} List with class and PLinq took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]", iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy ); } static void BenchmarkDictionary ( SampleHolder holder, int iteration ) { var dictionary = new Dictionary<int, string> ( holder.Samples.Count ); dictionary.Count ( ); stopwatch.Restart ( ); foreach ( var sample in holder.Samples ) dictionary.Add ( sample.Key, sample.Value ); var dummy = 0; foreach ( var sample in dictionary.OrderBy ( kv => kv.Key ) ) dummy += sample.Key; var elapsed = stopwatch.Elapsed; Console.WriteLine ( "#{0} Dictionary took {1} ms. [ticks: {2}, elements: {3} dummy: {4}]", iteration, elapsed.TotalMilliseconds, elapsed.Ticks, holder.Samples.Count, dummy ); } static Stopwatch stopwatch = new Stopwatch ( ); } class SampleHolder { public static SampleHolder Generate ( int numberOfSamples ) { var holder = new SampleHolder ( ) { Samples = new List<KeyValuePair<int, string>> ( numberOfSamples ) }; for ( int i = 0; i < numberOfSamples; ++i ) holder.AddSample ( ); // remove duplicate integers. (ordinary dictionaries cannot handle them) holder.Samples = holder.Samples .GroupBy ( kv => kv.Key ) .Select ( group => group.First ( ) ) .ToList ( ); return holder; } public void AddSample ( ) { // feed kvp with random values.. Samples.Add ( new KeyValuePair<int, string> ( randomizer.Next ( ), randomizer.Next ( ).ToString ( ) ) ); } public List<KeyValuePair<int, string>> Samples { get; set; } static Random randomizer = new Random ( ); } }