【问题标题】:How to find a string element in one of several arraylists inside a list?? C#如何在列表中的几个数组列表之一中查找字符串元素? C#
【发布时间】:2016-12-12 13:42:26
【问题描述】:

我正在与列表中的数组列表作斗争。有几个问题。

首先:我删除日志的试验正在运行,但我触发了异常,不知道该怎么做(参见案例 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.
        }
    }   

【问题讨论】:

  • 情况4应该发生什么异常?

标签: c# list search edit


【解决方案1】:

在 foreach 中迭代列表时,您无法修改列表。来自MSDN

foreach 语句用于遍历集合以获取您想要的信息,但不能用于从源集合中添加或删除项目,以避免不可预知的副作用。如果您需要在源集合中添加或删除项目,请使用 for 循环。

您可以考虑使用 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.");
    }
}

【讨论】:

  • 感谢您的帮助,但为什么 i - - ; ??
  • i-- 是为了补偿删除一个元素。
【解决方案2】:

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

这行有问题:

if (item.Contains(erase))

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

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

编辑

鉴于您的搜索字符串应该是完全匹配的,您应该会找到该帖子 - 但您也会找到帖子正文为“日志编号:2”(可能是不同的邮政)。你真的只想检查ítem[0]


回答您的第二个问题:您已经知道如何查找帖子;你是为“删除”案例做的。找到要更改的内容后,只需更新内容,就像您在创建新帖子时所做的那样:

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;
    }
}

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

【讨论】:

  • Thx Petter,我一喝咖啡就试试这个,我从早上就开始了。我会让你知道结果。
  • 我试过了,效果很好。我正在慢慢学习这一点,现在才 9 周;)谢谢帮助。
  • Lykke 直到视频。
【解决方案3】:

尝试使用 RemoveAll:

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

List.RemoveAll Method @ MSDN

【讨论】:

  • 如果(比如说)帖子#5 的帖子正文的值为“Log number: 2”,它将与实际的#2 一起被删除。 x[0].Contains(erase) 会更好。
  • 我没有从问题中找到这个要求。此外,如果 x 为空,则代码将失败。
【解决方案4】:

正如其他人所指出的,当您使用 foreach 对其进行迭代时,您无法修改 logBook 集合。您可以使用 for 循环在列表中向后工作,并在找到您要查找的帖子时使用 RemoveAt。

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

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;
    }
}

【讨论】:

  • 几个问题:请理解我是编码新手,但“logBook[i][0]”到底指的是什么(这到底是什么意思。我相信我得到了一个列表,其中包含 Array[] 的元素(类型字符串),而该列表又包含 4 个字符串元素(logNR、timeDate、post 和 title)。这一切都像一棵树(我试图了解它)。为什么 for-loop 向后循环?谢谢帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-18
  • 2023-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
相关资源
最近更新 更多