如何在列表中的几个数组列表之一中找到字符串元素? C#

How to find a string element in one of several arraylists inside a list?? C#

我正在努力处理列表中的数组列表。有几个问题。

首先:我尝试删除一个 logg 是有效的,但我触发了一个异常,不知道该怎么做(见案例 4)。

其次:我想能够编辑任何现有日志(尚未在菜单中),更像是更改现有日志中的一个字符串,如 "post" 或“title.谁能给我提示??

{
    List<string[]> logBook = new List<string[]> { }; // Skapar en lista för arrayer av typen string.
    DateTime time = DateTime.Now;  // Sätter variabeln time till lokal tid på datorn.

    int logCount = 0;  // Deklarerar en variabel för att räkna inläggen,
                       // läggs utanför case 1 så att den är nollad vid uppstart av programmet 
                       // och när den kommer in i case 1 så räknar den upp.

    Console.WriteLine("\t" + time.ToLongDateString()); // Skriver ut datum i ett passande format för en loggbok.
    Console.WriteLine("\n\tWelcome to the Logbook!\n");  // Skriver ut välkomsttext en gång vid uppstart,
                                                         // därför läggs den utanför while-loopen.

    bool go = true; // Booleanskt värde för while-loopen som ska ligga för menyn och som br

    while (go)
        try         // Exception-block som fångar upp om användaren knappar in ex. bokstäver som val i menyn (förhindrar körfel).
        {
            {
                Console.WriteLine("");  //Skapar ny rad. Användaren ska inte känna att det blandar ihop sig.
                Console.WriteLine("\t[1] Write a new post");
                Console.WriteLine("\t[2] Search for a post");
                Console.WriteLine("\t[3] Display all posts");
                Console.WriteLine("\t[4] Remove a post");
                Console.WriteLine("\t[5] Quit");

                Console.Write("\n\tSelect from menu: ");

                int menu = Convert.ToInt32(Console.ReadLine());  //Gör om inmatad sträng till heltal.
                Console.WriteLine("");  //Skapar mellanrum innan nästa direktiv till användaren (Estetiskt).

                switch (menu)
                {
                    case 1:

                        logCount++;
                        string logNr = "Log number: " + logCount.ToString();  // Skapar en nurering av loggarna.

                        string timeDate = time.ToLongDateString();  // Ger oss ett datum för inlägget.

                        Console.Write("\tWrite a title to your post: ");
                        string title = "Title: " + Console.ReadLine();  // Ger oss en titel för inlägget.

                        Console.Write("\n\tPost is created " + timeDate + "\n\n\tWrite your post: ");

                        string post = Console.ReadLine();

                        string[] arr = new string[4];
                        arr[0] = logNr;  
                        arr[1] = timeDate;
                        arr[2] = title;
                        arr[3] = post;

                        logBook.Add(arr);
                        break;

                    case 2:
                        Console.Write("\tWrite a searchword or a date (yyyy-mm-dd): ");
                        string keyword = Console.ReadLine();
                        Console.WriteLine("");

                        bool anyFound = false;

                        foreach (string[] item in logBook)  //För varje element(item) i Listan(logBook) dvs (arr[i])
                        {
                            foreach (string element in item)  //För varje element(element) i arr[i] dvs (arr[0], arr[1], arr[2])
                            {
                                if (element.Contains(keyword))  // Om arr[0], arr[1] eller arr[2] innhåller sökord....,
                                                                // letar efter en substring(keyword) inom strängen.
                                {
                                    foreach (string s in item)  // Skriv ut varje arr[i] i det elementet(item) (dvs hela den loggen)
                                                                // I detta fall tre varv, datum, titel, text(post) = 3 strängar.
                                                                // För att användaren ska kunna se hela loggen som sökordet finns i.
                                    {
                                        Console.WriteLine("\t" + s);
                                    }
                                    Console.WriteLine("");
                                    anyFound = true;  // Kliver ur loopen då uppdraget är slutfört, bool ändrar värde till true.
                                }
                            }
                        }
                        if (!anyFound)  // Om inget hittas dvs bool är fortfarande oförändrat genomförs utskrift.
                            Console.WriteLine("\tSearchword couldn't be found.");
                        break;

                    case 3:
                        Console.WriteLine("\tThese are the current posts in Logbook.\n ");

                        foreach (var item in logBook)  //För varje element(item) i Listan(logBook) dvs (arr[i])
                        {
                            foreach (string element in item)  //För varje element(element) i arr[i] dvs (arr[0], arr[1], arr[2])
                            {
                                Console.WriteLine("\t" + element);
                            }
                                Console.WriteLine("");
                        }
                        break;

                    case 4:

                        Console.Write("\tWhich log number do you want to remove? : ");
                        string erase = "Log number: " + Console.ReadLine();

                        foreach (string[] item in logBook)  // För varje element(item) i Listan(logBook) dvs (arr[i])
                        {
                            if (item.Contains(erase))  // Om arr[0], arr[1] eller arr[2] innhåller sökord....,
                            {
                                logBook.Remove(item);  // raderas hela elementet(item/arr[i])
                                Console.WriteLine("\t" + erase + " is now removed from logbook.");
                            }
                        }


                        break;

                    case 5:
                        go = false; // Avbryter while-loopen och med det avslutar programmet.
                        break;

                    default:        // Fångar upp om användaren skriver in ett tal utanför valmenyn.
                        Console.WriteLine("\tChoose from menu 1 - 4");
                        break;
                }
            }
        }
        catch(Exception e)
        {
            Console.WriteLine("");  //Estetisk för att användaren ska få ny rad innan meddelandet.
            Console.WriteLine("\tChoose from menu by using number 1 - 4\n" + e); //Aktiveras om användaren knappar in annat än heltal.
        }
    }   

在 foreach 中迭代列表时不能修改列表。来自 MSDN:

The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.

您可以考虑使用 for 循环而不是 foreach 吗?大致如下:

for (var i = 0; i < logbook.Count; i++)
{
    if (logbook[i].Contains(erase))
    {
        logBook.RemoveAt(i);
        i--;
        Console.WriteLine("\t" + erase + " is now removed from logbook.");
    }
}

尝试改用 RemoveAll:

logBook.RemoveAll(log => log.Any(row => row.Contains(erase)));

List.RemoveAll Method @ MSDN

正如其他人所指出的,您不能在使用 foreach 迭代 logBook 集合时修改它。您可以使用 for 循环在列表中向后工作,并在找到要查找的 post 时使用 RemoveAt。

由于给定日志编号最多可以有一个 post,因此您还应该在循环中包含一个中断,以便在找到并删除 post 后退出。像这样:

for (var i = logBook.Count - 1; i >= 0; i--)
{
    if (logBook[i][0] == erase)
    {
        logBook.RemoveAt(i);
        Console.WriteLine("\t" + erase + " is now removed from logbook.");
        break;
    }
}

@ScottPerham 是正确的,您不能在迭代时修改集合。由于您可能只想删除一项,因此您也可以通过在删除该项后 break 跳出循环来解决此问题。

这行有问题:

if (item.Contains(erase))

item是一个字符串数组;调用的 Contains 方法是集合的一种方法,它检查集合中的任何元素是否(完全)匹配提供的输入。这与查找子字符串的 string.Contains 不同。你想要这个:

if (item[0].Contains(erase))

编辑

鉴于您的搜索字符串应该是完全匹配的,您应该找到 post -- 但您也会找到任何 post,其中 post 的正文是,比如,"Log number: 2"(可能是不同的 post)。你真的只想检查 ítem[0].


回答你的第二个问题:你已经知道如何找到 post;你在 "delete" 案例中这样做了。找到要更改的内容后,只需更新内容,类似于创建新内容时所做的 post:

Console.Write("\tWhich log number do you want to change? : ");
string change = "Log number: " + Console.ReadLine();

foreach (string[] item in logBook)  // För varje element(item) i Listan(logBook) dvs (arr[i])
{
    if (item[0].Contains(change))  // Om arr[0], arr[1] eller arr[2] innhåller sökord....,
    {
        string timeDate2 = time.ToLongDateString();  // Ger oss ett datum för inlägget.

        Console.Write("\tWrite a title to your post: ");
        string title2 = "Title: " + Console.ReadLine();  // Ger oss en titel för inlägget.

        Console.Write("\n\tPost is created " + timeDate2 + "\n\n\tWrite your post: ");

        string post2 = Console.ReadLine();

        item[1] = timeDate2;
        item[2] = title2;
        item[3] = post2;
    }
}

请注意,此代码的结构还有改进的余地。