Permalänk
Medlem

Linjär Sökning C#

Hej, skulle vilja ha lite hjälp med Linjär Sökning. Innan använda jag mig av FOREACH men det måste vara en linjär sökning vilket jag förstått är FOR. Så min kod ser ut så här nu...
Jag vill som sagt att alla inlägg som innehåller sökordet skall hittas.

{ List<string[]> loggBoken = new List<string[]> { }; string[] inlägg = new string[3] ; DateTime datumTid = DateTime.Now; Console.WriteLine("\t" + datumTid); bool isRunning = true; while (isRunning) //try { { Console.WriteLine("\n\n\tVälkommen till Loggboken!"); Console.WriteLine( "\n\t[1]Skriv nytt inlägg" + "\n\t[2]Sök inlägg" + "\n\t[3]Skriv ut loggar" + "\n\t[4]Avsluta"); Console.Write("\tVälj: "); int val; int.TryParse(Console.ReadLine(), out val); switch (val) { case 1: Console.Write("Skriv titel: "); inlägg = new string[3]; inlägg[0] = Console.ReadLine(); Console.Clear(); Console.WriteLine("Skriv inlägget: "); Console.WriteLine(datumTid); Console.WriteLine(inlägg[0]); inlägg[1] = Console.ReadLine(); Console.Clear(); datumTid = DateTime.Now; var skrevs = Convert.ToString(datumTid); inlägg[2] = skrevs; loggBoken.Add(inlägg); break; case 2: Console.Write("Skriv in ett sökord: "); string ord = Console.ReadLine(); bool sök = false; for (int i = 0; i < inlägg.Length; i++) { if (inlägg[i] == ord) { Console.WriteLine("Följande hittades" + inlägg[i]); sök = true; } } if (!sök) { Console.WriteLine("Din sökning misslyckades!"); } break; case 3: Console.WriteLine("\nFöljande inlägg finns i loggboken!"); foreach (string[] item in loggBoken) { Console.WriteLine("Titel: " + item[0] +"\nInlägg: "+ item[1] + "\n" + item[2] + "\n\n---------------------------------"); } break; case 4: Console.WriteLine("\nHEJ DÅ!"); Console.ReadLine(); return; default: Console.WriteLine("\nVälj i menyn, 1-4!"); break; } } } /*} catch (Exception) { Console.WriteLine("Nu blev det knasigt!"); }*/ Console.ReadLine(); }

Permalänk
Medlem
Skrivet av micke_mj:

Hej, skulle vilja ha lite hjälp med Linjär Sökning. Innan använda jag mig av FOREACH men det måste vara en linjär sökning vilket jag förstått är FOR. Så min kod ser ut så här nu...

En linjär sökning betyder att man sekventiellt kontrollerar ett element i taget tills man hittar vad man söker. Vad man använder för att gå igenom listan har ingen betydelse, så det finns inget som säger att du inte kan använda foreach om det passar. För att kolla om en sträng innehåller en annan sträng kan du använda String.Contains.

Permalänk
Medlem
Skrivet av perost:

En linjär sökning betyder att man sekventiellt kontrollerar ett element i taget tills man hittar vad man söker. Vad man använder för att gå igenom listan har ingen betydelse, så det finns inget som säger att du inte kan använda foreach om det passar. För att kolla om en sträng innehåller en annan sträng kan du använda String.Contains.

Det har du helt rätt i men vi skall använda oss av:
for och inte foreach.
Och det lyckas jag inte med.

case 2: Console.Write("Skriv in ett sökord: "); string word = Console.ReadLine();//skapar varibel för sökordet bool search = false; // true or false foreach (string[] item in loggBoken) // loopar genom loggboken för att hitta sökordet { if (item[0].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0 || item[1].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) // letar efter ordmatchning i både titel och inläggstext { Console.WriteLine("Titel: " + item[0] + "\nInlägg: " + item[1] + "\nSkrevs: " + item[2] + "\n---------------------------------"); // skriver ut titel, inlägg, datum search = true; } } if (!search) // om sökord ej finns i loggbok skrevs nedan ut { Console.WriteLine("Din sökning misslyckades!"); } break;

Permalänk
Medlem

case 2: Console.Write("Skriv in ett sökord: "); string ord = Console.ReadLine(); bool sök = false; // Du loopar igenom inlägg, inte Loggboken. //Använd samma princip men för att ta reda på längden på en lista använder man .Count for (int i = 0; i < inlägg.Length; i++) { // I varje inlägg är det bara index 0 och 1 som innehåller text som ska sökas på if (inlägg[i] == ord) { Console.WriteLine("Följande hittades" + inlägg[i]); sök = true; } } if (!sök) { Console.WriteLine("Din sökning misslyckades!"); } break;

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem
Skrivet av kundun:

case 2: Console.Write("Skriv in ett sökord: "); string ord = Console.ReadLine(); bool sök = false; // Du loopar igenom inlägg, inte Loggboken. //Använd samma princip men för att ta reda på längden på en lista använder man .Count for (int i = 0; i < inlägg.Length; i++) { // I varje inlägg är det bara index 0 och 1 som innehåller text som ska sökas på if (inlägg[i] == ord) { Console.WriteLine("Följande hittades" + inlägg[i]); sök = true; } } if (!sök) { Console.WriteLine("Din sökning misslyckades!"); } break;

Försökt med samma princip men funkar ej=) WORD = cannot convert string to String Array.

case 2: Console.Write("Skriv in ett sökord: "); string word = Console.ReadLine();//skapar varibel för sökordet bool search = false; // true or false for (int i = 0; i < loggBoken.Count; i++) { if (loggBoken[0].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0 || loggBoken[1].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) { Console.WriteLine("Följande hittades: " + loggBoken[i]); search = true; } }

Permalänk
Medlem

if (loggBoken[0].IndexOf(word...

Här kollar du position 0 i arrayen, och det gör du för varje iteration. Drt är ju inte det du vill!
Variabeln i ska användas för att komma åt rätt position i arrayen; Loggbok[i] ger dig alltså åtkomst till varje position i arrayen, allteftersom i ändrar värde för varje loop.
Varje position i loggboken innehåller ju ett inlägg som du vill kolla och det kommer du åt på samma sätt, fast där vill du kolla position 0 och 1 varje gång.
Alltså: Loggboken[i].inlägg[0].indexOf....

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.

Permalänk
Medlem

Kan rekommendera att bryta ut inlägg i klasser istället för att ha dem som indexerade arrayer,
det blir betydligt enklare att läsa och förstå koden när man ser ett namn istället för siffra.

Ett annat tips är att använda enum, vilket också förbättrar läsbarheten, men ni kanske inte kommit så långt ännu?

Gjorde en liten snabb ny implementation som du kanske kan kika på, kom senare på att man kanske borde brutit ut även meny och loggbok i klasser, och så skall man ju helst undvika statiska metoder och variabler om man kan. Jag hade troligtvis valt engelska namn, men det blev svenska den här gången.

using System; using System.Collections.Generic; namespace LoggBok { public class Program { private enum MenyOperation { NyttInlägg = 1, SökInlägg, LoggUtskrift, Avsluta } private class MenyVal { public MenyOperation Operation; public string Beskrivning; } private static MenyVal[] _meny = new[] { new MenyVal { Operation = MenyOperation.NyttInlägg, Beskrivning = "Skriv nytt inlägg" }, new MenyVal { Operation = MenyOperation.SökInlägg, Beskrivning = "Sök inlägg" }, new MenyVal { Operation = MenyOperation.LoggUtskrift, Beskrivning = "Skriv ut loggar" }, new MenyVal { Operation = MenyOperation.Avsluta, Beskrivning = "Avsluta" } }; public class Inlägg { public string Titel; public string Stycke; public DateTime Skapad; public void SkrivUt() { Program.SkrivUt($"Titel: {Titel}", 1); Program.SkrivUt($"Inlägg: {Stycke}", 1); Program.SkrivUt(Convert.ToString(Skapad), 3); } } private static List<Inlägg> _loggBoken = new List<Inlägg>(); static void Main(string[] args) { SkrivUt(Convert.ToString(DateTime.Now), 3, true); MenyOperation valdOperation = 0; do { SkrivUtVälkomstMeny(); valdOperation = LäsInMenyVal(); HanteraMenyVal(valdOperation); } while (valdOperation != MenyOperation.Avsluta); Console.ReadLine(); } public static void SkrivUt(string text, int antalRadBrytningar = 0, bool inledandeTab = false) { if (inledandeTab) Console.Write("\t"); Console.Write(text); for (int i = 0; i < antalRadBrytningar; i++) Console.WriteLine(); } private static void SkrivUtVälkomstMeny() { SkrivUt("Välkommen till Loggboken!", 2, true); foreach (MenyVal menyVal in _meny) SkrivUt($"[{(int)menyVal.Operation}] {menyVal.Beskrivning}", 1, true); } private static MenyOperation LäsInMenyVal() { MenyOperation valdOperation; var inData = Console.ReadLine(); Enum.TryParse<MenyOperation>(inData, out valdOperation); return valdOperation; } private static void HanteraMenyVal(MenyOperation valdOperation) { switch (valdOperation) { case MenyOperation.NyttInlägg: NyttInlägg(); break; case MenyOperation.SökInlägg: SökInlägg(); break; case MenyOperation.LoggUtskrift: LoggUtskrift(); break; case MenyOperation.Avsluta: SkrivUt("HEJ DÅ!"); break; default: SkrivUt("Välj i menyn, 1-4!", 1); break; } } private static void NyttInlägg() { var inlägg = new Inlägg(); SkrivUt("Skriv titel: "); inlägg.Titel = Console.ReadLine(); Console.Clear(); SkrivUt("Skriv inlägget:", 1); SkrivUt(Convert.ToString(DateTime.Now),1); SkrivUt(inlägg.Titel,1); inlägg.Stycke = Console.ReadLine(); Console.Clear(); inlägg.Skapad = DateTime.Now; _loggBoken.Add(inlägg); } private static void SökInlägg() { SkrivUt("Skriv in ett sökord: "); var sökTerm = Console.ReadLine(); int matchadeInlägg = 0; foreach (var inlägg in _loggBoken) { bool matchadeTitel = inlägg.Titel.IndexOf(sökTerm, StringComparison.OrdinalIgnoreCase) >= 0; bool matchadeStycke = inlägg.Stycke.IndexOf(sökTerm, StringComparison.OrdinalIgnoreCase) >= 0; if(matchadeStycke || matchadeTitel) { matchadeInlägg++; Console.WriteLine("Söktermen hittades i titel eller stycke: "); inlägg.SkrivUt(); } } if (matchadeInlägg == 0) SkrivUt("Din sökning misslyckades!", 1); } private static void LoggUtskrift() { SkrivUt("Följande inlägg finns i loggboken!", 1); foreach (var inlägg in _loggBoken) inlägg.SkrivUt(); } } }

Permalänk
Medlem
Skrivet av kundun:

if (loggBoken[0].IndexOf(word...

Här kollar du position 0 i arrayen, och det gör du för varje iteration. Drt är ju inte det du vill!
Variabeln i ska användas för att komma åt rätt position i arrayen; Loggbok[i] ger dig alltså åtkomst till varje position i arrayen, allteftersom i ändrar värde för varje loop.
Varje position i loggboken innehåller ju ett inlägg som du vill kolla och det kommer du åt på samma sätt, fast där vill du kolla position 0 och 1 varje gång.
Alltså: Loggboken[i].inlägg[0].indexOf....

Skickades från m.sweclockers.com

men word (varibeln) går inte att använda.

Permalänk
Medlem
Skrivet av Lento:

Kan rekommendera att bryta ut inlägg i klasser istället för att ha dem som indexerade arrayer,
det blir betydligt enklare att läsa och förstå koden när man ser ett namn istället för siffra.

Ett annat tips är att använda enum, vilket också förbättrar läsbarheten, men ni kanske inte kommit så långt ännu?

Gjorde en liten snabb ny implementation som du kanske kan kika på, kom senare på att man kanske borde brutit ut även meny och loggbok i klasser, och så skall man ju helst undvika statiska metoder och variabler om man kan. Jag hade troligtvis valt engelska namn, men det blev svenska den här gången.

using System; using System.Collections.Generic; namespace LoggBok { public class Program { private enum MenyOperation { NyttInlägg = 1, SökInlägg, LoggUtskrift, Avsluta } private class MenyVal { public MenyOperation Operation; public string Beskrivning; } private static MenyVal[] _meny = new[] { new MenyVal { Operation = MenyOperation.NyttInlägg, Beskrivning = "Skriv nytt inlägg" }, new MenyVal { Operation = MenyOperation.SökInlägg, Beskrivning = "Sök inlägg" }, new MenyVal { Operation = MenyOperation.LoggUtskrift, Beskrivning = "Skriv ut loggar" }, new MenyVal { Operation = MenyOperation.Avsluta, Beskrivning = "Avsluta" } }; public class Inlägg { public string Titel; public string Stycke; public DateTime Skapad; public void SkrivUt() { Program.SkrivUt($"Titel: {Titel}", 1); Program.SkrivUt($"Inlägg: {Stycke}", 1); Program.SkrivUt(Convert.ToString(Skapad), 3); } } private static List<Inlägg> _loggBoken = new List<Inlägg>(); static void Main(string[] args) { SkrivUt(Convert.ToString(DateTime.Now), 3, true); MenyOperation valdOperation = 0; do { SkrivUtVälkomstMeny(); valdOperation = LäsInMenyVal(); HanteraMenyVal(valdOperation); } while (valdOperation != MenyOperation.Avsluta); Console.ReadLine(); } public static void SkrivUt(string text, int antalRadBrytningar = 0, bool inledandeTab = false) { if (inledandeTab) Console.Write("\t"); Console.Write(text); for (int i = 0; i < antalRadBrytningar; i++) Console.WriteLine(); } private static void SkrivUtVälkomstMeny() { SkrivUt("Välkommen till Loggboken!", 2, true); foreach (MenyVal menyVal in _meny) SkrivUt($"[{(int)menyVal.Operation}] {menyVal.Beskrivning}", 1, true); } private static MenyOperation LäsInMenyVal() { MenyOperation valdOperation; var inData = Console.ReadLine(); Enum.TryParse<MenyOperation>(inData, out valdOperation); return valdOperation; } private static void HanteraMenyVal(MenyOperation valdOperation) { switch (valdOperation) { case MenyOperation.NyttInlägg: NyttInlägg(); break; case MenyOperation.SökInlägg: SökInlägg(); break; case MenyOperation.LoggUtskrift: LoggUtskrift(); break; case MenyOperation.Avsluta: SkrivUt("HEJ DÅ!"); break; default: SkrivUt("Välj i menyn, 1-4!", 1); break; } } private static void NyttInlägg() { var inlägg = new Inlägg(); SkrivUt("Skriv titel: "); inlägg.Titel = Console.ReadLine(); Console.Clear(); SkrivUt("Skriv inlägget:", 1); SkrivUt(Convert.ToString(DateTime.Now),1); SkrivUt(inlägg.Titel,1); inlägg.Stycke = Console.ReadLine(); Console.Clear(); inlägg.Skapad = DateTime.Now; _loggBoken.Add(inlägg); } private static void SökInlägg() { SkrivUt("Skriv in ett sökord: "); var sökTerm = Console.ReadLine(); int matchadeInlägg = 0; foreach (var inlägg in _loggBoken) { bool matchadeTitel = inlägg.Titel.IndexOf(sökTerm, StringComparison.OrdinalIgnoreCase) >= 0; bool matchadeStycke = inlägg.Stycke.IndexOf(sökTerm, StringComparison.OrdinalIgnoreCase) >= 0; if(matchadeStycke || matchadeTitel) { matchadeInlägg++; Console.WriteLine("Söktermen hittades i titel eller stycke: "); inlägg.SkrivUt(); } } if (matchadeInlägg == 0) SkrivUt("Din sökning misslyckades!", 1); } private static void LoggUtskrift() { SkrivUt("Följande inlägg finns i loggboken!", 1); foreach (var inlägg in _loggBoken) inlägg.SkrivUt(); } } }

Snyggt!
Men jag måste tyvärr söka med FOR och inte foreach som jag använde innan och har svårigheter med det...

Permalänk
Medlem
Skrivet av kundun:

if (loggBoken[0].IndexOf(word...

Här kollar du position 0 i arrayen, och det gör du för varje iteration. Drt är ju inte det du vill!
Variabeln i ska användas för att komma åt rätt position i arrayen; Loggbok[i] ger dig alltså åtkomst till varje position i arrayen, allteftersom i ändrar värde för varje loop.
Varje position i loggboken innehåller ju ett inlägg som du vill kolla och det kommer du åt på samma sätt, fast där vill du kolla position 0 och 1 varje gång.
Alltså: Loggboken[i].inlägg[0].indexOf....

Skickades från m.sweclockers.com

funkar inte med

for (int i = 0; i < loggBoken.Count; i++) { if (loggBoken[i].post[0].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0)

Permalänk
Medlem
Skrivet av micke_mj:

funkar inte med

loggBoken[i].post[0].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0)

Är det inte

loggBoken[i].post[x].Titel

du vill kolla mot? (Eller post.Stycke)

Permalänk
Medlem
Skrivet av hultron:

Är det inte

loggBoken[i].post[x].Titel

du vill kolla mot? (Eller post.Stycke)

Detta är hur det ser ut för tillfället!

static void Main(string[] args) { List<string[]> loggBoken = new List<string[]> { }; //skapar lista string[] post = new string[3]; // skapa array för inläggen DateTime dateTime = DateTime.Now; // för att kunna spara ner tid o datum i inläggen Console.WriteLine("\t" + dateTime); // skriver ut dagens datum när consolen öppnar bool isRunning = true; while (isRunning) // loopar tills användaren väljer att avsluta //try { { Console.WriteLine("\n\n\tVälkommen till Loggboken!"); Console.WriteLine( "\n\t[1]Skriv nytt inlägg" + "\n\t[2]Sök inlägg" + "\n\t[3]Skriv ut loggar" + "\n\t[4]Avsluta"); Console.Write("\tVälj: "); // skriver ut meny int val; // int för menyvalen 1-4 int.TryParse(Console.ReadLine(), out val); // parsar integern så att anvädaren inte crashar programmet switch (val) { case 1: Console.Write("Skriv titel: "); post = new string[3]; post[0] = Console.ReadLine();// sparar ner första inlägget Titel Console.Clear(); // rensar consolen Console.WriteLine("Skriv inlägget: "); Console.WriteLine(dateTime); // skriver ut datumTid //Console.WriteLine(inlägg[0]); post[1] = Console.ReadLine(); // andra inlägget sparas Console.Clear(); // rensar consolen dateTime = DateTime.Now; string wrote = Convert.ToString(dateTime); // skapar ny varibel som gör att dateTime kan sparas ner som sträng post[2] = wrote; // sparar ner dateTime loggBoken.Add(post);// lägger till alla 3 inläggen i loggboken break; case 2: Console.Write("Skriv in ett sökord: "); string word = Console.ReadLine();//skapar varibel för sökordet bool search = false; // true or false for (int i = 0; i < loggBoken.Count; i++) { if (loggBoken[0].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0 || loggBoken[1].IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0) { Console.WriteLine("Följande hittades: " + loggBoken[i]); search = true; } } if (!search) // om sökord ej finns i loggbok skrevs nedan ut { Console.WriteLine("Din sökning misslyckades!"); } break; case 3: Console.WriteLine("\nFöljande inlägg finns i loggboken!"); SkrivUtLogg(loggBoken); break; case 4: HejDa(); // metodanrop som avslutar loggboken som säger HejDå return; default: Console.WriteLine("\nVälj i menyn, 1-4!"); // fångar upp alla val utanför 1-4 break; } } } Console.ReadLine(); } static void HejDa() // metod för case 4 { Console.WriteLine("\nHEJ DÅ!"); Console.ReadLine(); } static void SkrivUtLogg(List<string[]> loggen) { foreach (string[] item in loggen) { Console.WriteLine("Titel: " + item[0] + "\nInlägg: " + item[1] + "\nSkrevs: " + item[2] + "\n\n---------------------------------"); } }

Behöver som sagt använda FOR.

Permalänk
Medlem
Skrivet av micke_mj:

Detta är hur det ser ut för tillfället!

Ok, kollade tydligen ett gammalt exempel.

Här får du något att kolla på även om du kanske inte vill ha dubbla for-loopar.

for (int i = 0; i < loggBoken.Count; i++) // Kollar igenom din lista av arrayer { for (int ii = 0; ii < loggBoken[i].Length; ii++) // Kollar igenom strängarna i arrayen { if (loggBoken[i][ii].Contains(word)) // Kollar om strängen innehåller ditt sökord { Console.WriteLine("Följande hittades: " + loggBoken[i][ii]); // Skriv ut strängen den träffade på search = true; } } }

Permalänk
Medlem
Skrivet av hultron:

Ok, kollade tydligen ett gammalt exempel.

Här får du något att kolla på även om du kanske inte vill ha dubbla for-loopar.

for (int i = 0; i < loggBoken.Count; i++) // Kollar igenom din lista av arrayer { for (int ii = 0; ii < loggBoken[i].Length; ii++) // Kollar igenom strängarna i arrayen { if (loggBoken[i][ii].Contains(word)) // Kollar om strängen innehåller ditt sökord { Console.WriteLine("Följande hittades: " + loggBoken[i][ii]); // Skriv ut strängen den träffade på search = true; } } }

Om man ska använda samma logik men till att radera ett inlägg, vad blir korrekt då?
Har följande, men .... om jag inte hittar titeln så skrivs du ut "Titeln finns inte, återgår till huvudmenyn" så många gånger som inlägg det finns. Jag förstår vrf det gör det men inte hur jag ska åtgärda..hm

static void ErasePost(List<string[]> erase) { string title = Console.ReadLine();//Sparar titeln på inlägget användaren vill radera for (int i = 0; i < erase.Count; i++) // Kollar igenom listan av arrayer { if (String.Equals(erase[i][0], title, StringComparison.OrdinalIgnoreCase)) // Kollar om strängen innehåller sökordet { erase.RemoveAt(0); } else { Console.WriteLine("Titeln finns inte, återgår till huvudmenyn"); } } }

Permalänk
Medlem

Du kan testa att ändra ett värde på en variabel istället för att skriva ut varje gång.
Tex: Innan loopen ger du variabeln titleExists värdet false.
I loopen ändrar du värdet till true om den hittar nån.
Efter loopen skriver du ut antingen 'hittade' eller 'hittade inte' beroende påvärdet på titleExists

Skickades från m.sweclockers.com

Visa signatur

Oldschool [å:ldsku:l] adj. Användandet av datorprodukter som är äldre än 3 månader.