【问题标题】:Dictionary Checking字典检查
【发布时间】:2011-11-01 00:26:27
【问题描述】:

我有一个列表,我在 foreach 循环中获取列表中的每个项目。

    private void saveButton_Click(object sender, EventArgs e)
    {
            if (saveFile1.ShowDialog() == DialogResult.OK)
            {
                StreamWriter sw = new StreamWriter(saveFile1.FileName);
                int i = 1;

                Dictionary<string, int> dictionary = new Dictionary<string, int>();

                foreach (var line in theFinalList)
                {
                    //compareList.Add(line.PartNumber[]);
                    if (!line.Name.Contains("FID") || !line.PartNumber.Contains("FIDUCIAL") ||
                        !line.PartNumber.Contains("EXCLUDES") || !line.PartNumber.Contains("excludes"))
                    {
                        //This doesn't work obviously.. :/
                        sw.WriteLine("( {0} 0 1 1 0 0 0 0 \"{1}\" \"{2}\" \"\" {3} 0 0 0 0 0 )",
                            i, line.PartDescription, line.PartNumber, partNumberOccurrences);
                    }

                    i++;
                }
            }

而且我在使用字典将行的每个部分存储在字典中并在发现 itemCounter 重复时增加它时遇到了麻烦。我正在尝试做这样的事情,但我无法弄清楚它的逻辑。

我只想输出 partNumber 1 次以及它发生的次数以及与 partNumber 在同一行的相应值。

输出如下所示:

( 1 0 1 1 0 0 0 0 "2125R_1.0" "136380" "" 18 0 0 0 0 0 )
( 2 0 1 1 0 0 0 0 "2125R_1.0" "128587" "" 41 0 0 0 0 0 )
( 3 0 1 1 0 0 0 0 "2125R_1.0" "138409" "" 11 0 0 0 0 0 )
( 4 0 1 1 0 0 0 0 "2125R_1.0" "110984" "" 8 0 0 0 0 0 )
( 5 0 1 1 0 0 0 0 "3216R_1.3" "114441" "" 6 0 0 0 0 0 )
( 6 0 1 1 0 0 0 0 "3216C_1.3" "2006722" "" 16 0 0 0 0 0 )
( 7 0 1 1 0 0 0 0 "3216C_1.3" "135732" "" 6 0 0 0 0 0 )

谁能帮我创建一个字典来做到这一点?

【问题讨论】:

    标签: c# dictionary contains


    【解决方案1】:

    您还可以为您的项目创建一个新类并存储这些项目的列表,然后使用 Linq 对结果进行分组 - 您可能会也可能不会觉得它更合乎逻辑:

    public class MyItem
    {
        public string Name { get; set; }
        public string PartNumber { get; set; } // I did this as string rather than int
        public string Description { get; set; }
    }
    
    public List<MyItem> items = new List<MyItem>();
    

    然后,您似乎想要对项目进行分组(此示例使用 Linq 并假设您已填充项目列表):

    IEnumerable<IGrouping<int, MyItem>> grouped = items
        .GroupBy(t => Convert.ToInt32(t.PartNumber))
        .OrderBy(t => t.Key);
    
    foreach(var item in grouped)
    {
        Console.WriteLine("Number of Occurances:" + item.Key);
        Console.WriteLine("Name: " + item.ElementAt(0).Name);
        Console.WriteLine("Description: " + item.ElementAt(0).Description);
        Console.WriteLine("\n --------------------------------- \n");
    }
    

    此示例假定具有相同部件号的所有产品都将具有相同的名称和描述。

    【讨论】:

    • 我尝试将其插入代码中,但.Orderby(t =&gt; t.Key) 部分似乎有问题...您能帮我解决这个问题吗?
    • Cannot implicitly convert type 'System.Linq.IOOrderedEnumerable&lt;System.Linq.IGroping&lt;string,Balancer.mainForm.MyItem&gt;&gt;' to 'System.Collections.Generic.IEnumerable&lt;System.Linq.Igrouping&lt;int,Balancer.mainForm.MyItem&gt;&gt;'. An explicit conversion exists (are you missing a cast?) 是什么意思..
    • 啊,是的。那是因为 PartNumber 在我的示例中是一个字符串。我会修改我的答案。
    • 不再有错误..但是当我尝试运行它时,没有任何输出显示..:/
    • 它在我的测试中工作正常。你确定你在正确的事情上调用 group 函数并且你在正确的事情上调用 Console.WriteLine 吗?
    【解决方案2】:

    我想你想要这样的东西:

    int value;
    if (!dictionary.TryGetValue(line.PartNumber, out value))
    {
        value = 0;
    }
    dictionary[line.PartNumber] = value + 1;
    

    【讨论】:

    • 你不需要if;如果未找到密钥,TryGetValue 会将 default(int)(又名 0)放入 value
    • @Daniel:那么我如何将其打印到StreamWriter 文件中?
    • 由于您只保存零件编号和字典中的出现次数,因此没有干净的方法可以从字典中输出您想要的内容。 AndyC 会给出更简洁的方法。但是,我认为您不需要创建一个新类,因为您在theFinalList 中的类似乎已经保存了您需要的所有数据。
    • @Daniel:哦,好吧..我正在尝试类似:sw.WriteLine(dictionary[line.PartNumber] + " " + value);,但我有一种感觉是 WAY 关闭.. 哈哈
    • @theNoobGuy:如果你只是想在创建完成后输出字典的数据,你可以使用这个:foreach(var kvp in dictionary) sw.WriteLine(kvp.Key+" "+kvp.Value);
    【解决方案3】:

    您还可以将匿名类型与 linq 一起使用,为您提供更简洁的解决方案。这是一个假设您的行是制表符分隔的示例。

            var lines = new[]
                            {
                                "R80\t123456\tsomething here1",
                                "R81\t123456\tsomething here1",
                                "R81\t123456\tsomething here1",
                            };
    
            var items = lines.Select(i => i.Split('\t')).Select(i => new {Name = i[0], PartNumber = i[1], Description = i[2]});
    
            var outLines =
                items.GroupBy(i => i.Name).Select(
                    i =>
                    string.Format("{0}\t{1}\t{2}\t{3}", i.First().Name, i.First().PartNumber, i.First().Description,
                                  i.Count()));
    
            foreach (var outLine in outLines)
            {
                Console.WriteLine(outLine);
            }
    
            Console.Read();
    

    【讨论】:

    • 当使用这个时,我似乎得到一个输出:System.Linq.Enumerable+WhereSelectEnumerableIterator2[System.Linq.IGrouping2[System.String,f__AnonymousType0`3[System.String,System .String,System.String]],System.String]
    • 那是因为您正在编写集合对象而不是集合中的每个项目。我已经编辑了示例以使其更加明显
    【解决方案4】:
    foreach (string word in lineList)
    {
        if (dictionary.ContainsKey(word)
            dictionary[word]++;
        else
            dictionary[word] = 1;
    }
    

    【讨论】:

      猜你喜欢
      • 2012-06-21
      • 2018-09-28
      • 2019-04-19
      • 2013-09-05
      • 2017-10-10
      • 2014-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多