【问题标题】:Adding and Couting items in a list在列表中添加和计数项目
【发布时间】:2011-08-09 20:56:17
【问题描述】:

假设我有一个如下所示的文件:

R34     128590    -74.498   109.728  0    0805_7  
R33     128590    -74.498   112.014  0    0805_7  
R15     128588    -68.910   127.254  0    0805_7  
R32     128587    -65.354   115.189  0    0805_7  
R35     128587    -65.354   117.348  0    0805_7  
R38     128590    -65.354   119.507  0    0805_7  

我想要做的是将 第 2 列 添加到列表中,并让计数器计算该项目出现的次数,并将其与数字一起输出,然后输出该数字的计数。

有没有办法使用列表来做到这一点?如果是这样,我该怎么做?

我尝试过搞乱事情,这就是我要去的地方..但它不能正常工作

int lineCount = 1;
int itemCounter = 0;

foreach (var item in aListBox.Items)
{
    // Creates a string of the items in the ListBox.
    var newItems = item.ToString();

    // Replaces any multiple spaces (tabs) with a single space.
    newItems = Regex.Replace(newItems, @"\s+", " ");

    // Splits each line by spaces.
    var eachItem = newItems.Split(' ');

    ### 
    ### HERE is where I need help ###
    ### 
    List<string> partList = new List<string>();

    partList.Add(eachItem[1]);
    if (partList.Contains(eachItem[1]))
        itemCounter++;
    else 
        partList.Add(eachItem[1]);

    sw.WriteLine(lineCount + ": "+ partList + ": " + itemCounter);
    lineCount++;
}

SO 对于上面的示例,它会输出:

1: 128590: 3        #lineCount, partList, itemCounter
2: 128588: 1
3: 128587: 2

有人可以帮我弄清楚如何正确地做到这一点吗?

【问题讨论】:

    标签: c# list count add


    【解决方案1】:

    使用linq with count and group by(参见计数分组部分)。

    在 foreach 循环外创建您的 partList 并在循环内添加每个项目,以便它包含所有元素:

    List<string> partList = new List<string>();
    foreach (var item in aListBox.Items)
    {
        //regex stuff here...
        partList.Add(eachItem[1]);
    } 
    

    (在您的示例中-{128590, 128590, 128588, 128587, 128587, 128590})
    然后使用 LINQ 输出结果-

    var elementsWithCounts = from p in partList
         group p by p into g
         select new { Item = g.Key, Count = g.Count()};
    

    【讨论】:

    • @sJhonny:我试过了,但 group by 部分有问题
    • @theNoobGuy- 首先,我没有对此进行测试,所以它肯定不是完美的(对不起..)。我的想法是让你了解这个概念;你看过我提供的例子吗?你有大致的想法吗?另外,我很乐意为您提供帮助,但您需要比“它有问题”更具体:错误消息/异常是什么......?
    • 对不起,应该是group p by p;我已经编辑了我的答案。现在应该可以了。
    • @sJhonny:一旦数据采用这种形式,我将如何输出?对不起,我不熟悉 LINQ
    【解决方案2】:

    我会使用 Linq 查询或字典

    类似

        List<string> items = new List<string>{"128590", "128590", "128588", "128587", "128587", "128590"};
        Dictionary<string,int> result = new Dictionary<string,int>();
    
        foreach( int item in items )
        {
            if(result.ContainsKey(item) )
                result[item]++;
            else
                result.Add(item,1);
        }
    
        foreach( var item in result )
            Console.Out.WriteLine( item.Key + ":" + item.Value );
    

    【讨论】:

      【解决方案3】:

      一旦你将项目按空格分割,我假设你有一个字符串数组,如下所示:

      [0] = "R34"
      [1] = "128590"
      [2] = "-74.498"
      [3] = "109.728"
      [4] = "0"
      [5] = "0805_7"
      

      您可以使用 Group By 操作简单地执行此操作。

      var items = aListBox.Items.Select(x => /* Split Code Here and Take Element 1 */).GroupBy(x => x);
      
      foreach(var set in items)
      {
           Console.WriteLine(set.Key + " appeared " + set.Count() + " times.");
      }
      

      【讨论】:

      • 那么我是否只需将我的代码添加到此处的拆分代码中并获取元素 1 部分?
      • 差不多。不过,这里的关键是 GroupBy() 方法。
      【解决方案4】:

      基本上,您试图通过迭代一次来做到这一点,但这并不能真正奏效,您将不得不迭代两次,否则每次在 foreach 中循环时都会输出一个结果,并且即使您准确,您每次都将输出一条新行。如果您需要真正使用列表而不是键控字典或哈希表(键=数字,值=计数),那么您需要先构建列表,然后汇总列表。您可以使用 LINQ Group By(有点简洁),或者创建一个功能类似于您已有的功能。如果您正在尝试学习概念,请查看下面的代码,它可能更简洁,但应该相当容易阅读。

      List<string> partList = new List<string>();
      List<string> displayedNumbers = new List<int>();
      
      // Build the original list first.
      foreach (var item in aListBox.Items)
      {
          // Creates a string of the items in the ListBox.
          var newItems = item.ToString();
      
          // Replaces any multiple spaces (tabs) with a single space.
          newItems = Regex.Replace(newItems, @"\s+", " ");
      
          // Splits each line by spaces.
          var eachItem = newItems.Split(' ');
      
          partList.Add(eachItem[1]);
      }
      
      // Now run through that list and count how many times the same number occurs.
      // You will need two loops for this since your list is a single dimension collection.
      foreach(var number in partList)
      {
        var innerList = partList;
      
      
        // set this to zero because we are going to find at least 1 duplicate.
        var count = 0;
      
        foreach(var additionalNumber in innerList)
        {
          if(additionalNumber == number)
           {
             // If we find anymore increase the count each time.
             count += 1;
           }
        }  
      
         // Now we have the full count of duplicates of the outer number in the list.
         // If it has NOT been displayed, display it.
         if(!displayedNumbers.Contains(number))
          { 
            sw.WriteLine(partList + ": " + count);
            displayedNumbers.Add(number);
          }
      
      }
      

      【讨论】:

      • 我喜欢这个。这样做的一个问题是,如果它到达同一个项目,它将再次重新打印它。这意味着如果数据看起来像这样: 1: 128590: 3\n 2: 128590: 3\n 3: 128588 : 1\n 4: 128587: 2\n 5: 128587: 2\n 6: 128590: 3 而不是只输出 eachItem[1] 1次
      • 哈,是的,对不起,我没有测试它,只是在网络编辑器中敲了它。
      • 你知道你会做些什么来改变它,让它只做一次吗?
      • 对不起,是的,我编辑它来处理它,基本上你必须跟踪显示的内容。同样,像哈希表或字典这样的键/值集合会更干净,但如果需要一个列表,这就是你必须完成的方式。
      • 哦,我明白了.. 这似乎仍然无法正常工作:(。它说对于最佳重载方法匹配存在一些无效参数
      【解决方案5】:

      使用哈希表而不是列表。您可以将密钥保存为 128590,... 并将值保存为它发生的次数。 在插入新值之前,请使用 Contains 操作检查它是否已经存在于哈希表中,以及它是否会增加值。

      【讨论】:

        【解决方案6】:

        我认为最大的问题是从文本字段的原始行到单个值。我的猜测是这是一个以制表符分隔的文件,具有已知的恒定列数,在这种情况下,您可以使用 String.Split() 来分隔子字符串。将字符串分开后,您可以使用一点 LINQ 轻松计算正确列的实例。给定文件行的列表或集合:

        var histogram = myListOfLines
            //Split each string along spaces or tabs, and discard any zero-length strings
            //caused by multiple adjacent delimiters.
           .Select(s=>s.Split(new[]{'\t',' '}, StringSplitOptions.RemoveEmptyEntries))
            //Optional; turn the array of strings produced by Split() into an anonymous type
           .Select(a=>new{Col1=a[0], Col2=a[1], Col3=a[2], Col4=a[3], Col5=a[4]})
            //Group based on the values of the second column.
           .GroupBy(x=>x.Col2)
            //Then, out of the grouped collection, get the count for each unique value of Col2.
           .Select(gx=>new{gx.Key, gx.Count()});
        

        【讨论】:

          猜你喜欢
          • 2013-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多