【问题标题】:Summing values across nested lists at each index在每个索引的嵌套列表中求和值
【发布时间】:2014-10-27 05:33:00
【问题描述】:

我有一个名为 _DataCollection 的 List<List<string>>,其中每个嵌套列表都有相同数量的值。尽管都是字符串,但嵌套列表中的值将是由字母数字字符、空字符串或货币值组成的字符串。例如

_DataCollection[0] = {"tom", "abc", "$525.34", "$123"}
_DataCollection[1] = {"dick", "xyz", "$100", "$234"}
_DataCollection[2] = {"harry", "", "$250.01", "$40"}
_DataCollection[2] = {"bob", "", "$250.01", ""}

我需要做的是想出一种方法来汇总所有嵌套列表中每个索引的所有值并将其添加到列表中:

newSumList[0] = "N/A" since "tom" + "dick" + "harry" + "bob" can't be aggregated.
newSumList[1] = "N/A" since "abc" + "xyz" + "" + "" can't be aggregated.
newSumList[2] = "1125.36"
newSumList[3] = "397" even though the last value of the last nested list is "".

基本上,为每个索引汇总嵌套列表中的所有数值。

我能想到的唯一方法是迭代这些并保持运行总数,但我想知道是否可以使用 LINQ 或其他方法来做到这一点。

【问题讨论】:

    标签: c# linq list nested


    【解决方案1】:

    试试这个:-

    decimal _temp =0;
    int ListLength = _DataCollection.First().Count();
                var query = _DataCollection.SelectMany(x => x).
                                           Select((v, i) => new { Val = v, Index = i % ListLength })
                                           .GroupBy(x => x.Index)
                                           .Select(z => z.Sum(y => decimal.TryParse(y.Val,out _temp) ? _temp : 0));
    

    工作Fiddle

    【讨论】:

      【解决方案2】:

      给你。

      var list = new List<List<string>>
      {
          new List<string> {"tom", "abc", "$525.34", "$123"},
          new List<string> {"dick", "xyz", "$100", "$234"},
          new List<string> {"harry", "", "$250.01", "$40"},
          new List<string> {"bob", "", "$250.01", ""}
      };
      
      decimal num;
      var itemsPerLine = list[0].Count; // 4
      var res = list.SelectMany(line => line);
                    .Select((s, i) => new { Text = s, Index = i })
                    .GroupBy(i => i.Index % itemsPerLine) // transformed matrix here
                    .Select(g => g.Sum(i => 
                         decimal.TryParse(i.Text, NumberStyles.AllowCurrencySymbol | 
                                                  NumberStyles.AllowDecimalPoint, 
                                                  new CultureInfo("en-US"), out num) 
                                                  ? num : 0));
      

      当然,您可以通过更改 NumberStyles 标志和文化信息来指定应识别为数字的内容。

      【讨论】:

        【解决方案3】:

        或者,对于不需要使用GroupBy 重新排列序列的不同方法:

                var culture = new CultureInfo("en-US");
                List<string> sums =
                    _DataCollection.Count == 0
                    ? new List<string>()
                    : Enumerable.Range(0, _DataCollection.First().Count)
                    .Select(i => _DataCollection.Select(list => list[i])
                               .Select(s => { decimal val; return string.IsNullOrEmpty(s) ? (decimal?)0 : decimal.TryParse(s, NumberStyles.Currency, culture, out val) ? (decimal?)val : (decimal?)null; })
                               .Aggregate((decimal?)0, (sum, val) => sum + val))
                    .Select(sum => sum.HasValue ? sum.Value.ToString(culture) : "N/A")
                    .ToList();
        

        【讨论】:

          【解决方案4】:
          List<List<string>> _DataCollection=new List<List<string>>();
                      _DataCollection.Add( new List<string> {"tom", "abc", "$525.34", "$123"});
          
                      _DataCollection.Add( new List<string> {"dick", "xyz", "$100", "$234"});
                      _DataCollection.Add( new List<string> {"harry", "", "$250.01", "$40"});
                      _DataCollection.Add( new List<string> {"bob", "", "$250.01", ""});
          
                      List<string> newSumList = new List<string>();
          
                      for (int i = 0; i < _DataCollection.Count; i++)
                      {
                          decimal Sum = 0;
                          string CurrentSumList;
                          string Comment;
                          decimal amount = 0;
                          for (int j = 0; j < _DataCollection.Count; j++)
                          {
                              bool IsDecimalAmount=decimal.TryParse( _DataCollection[j][i].Replace('$','0'),out amount);
                              if (IsDecimalAmount)
                              {
          
                                  Sum += amount;
                              }
                              else
                              {
                                  Comment = "String";
          
                              }
                          }
                          CurrentSumList = Sum.ToString();
                          newSumList.Add(CurrentSumList);
                      }
          

          我已经实现了它,它给了我结果。

          【讨论】:

            【解决方案5】:
            // Replace $value with value and remove all non-value strings
            var dollars = _DataCollection
                .Select(l => l.Select(str => str.Contains('$') ? str.Split('$')[1] : string.Empty));
            
            var newSumList = new List<double>();
            
            // Add all values in a new list
            for (int i = 0; i < _DataCollection[0].Count; i++)
            {
                double toAdd = 0;
                foreach (var entry in dollars)
                {
                    // If entry is a value, parse it, 0 otherwise
                    var value = entry.ElementAt(i) != string.Empty ? double.Parse(entry.ElementAt(i)) : 0;
                    toAdd = toAdd + value;
                }
                newSumList.Add(toAdd);
            }
            newSumList.ForEach(Console.WriteLine);
            

            【讨论】:

              【解决方案6】:

              无需多次迭代并支持空源列表

              var list = new List<string[]>
              {
                  new [] {"tom", "abc", "$525.34", "$123"},
                  new [] {"dick", "xyz", "$100", "$234"},
                  new [] {"harry", "", "$250.01", "$40"},
                  new [] {"bob", "", "$250.01", ""}
              };
              var cutlure = new CultureInfo("en-US");
              var result = list.Aggregate((decimal[])null, (sums, strings) =>
                  {
                      if (sums == null)
                          sums = Enumerable.Repeat(decimal.MinValue, strings.Length).ToArray();
                      for (int i = 0; i < strings.Length; i++)
                      {
                          decimal value;
                          if (decimal.TryParse(strings[i], NumberStyles.Currency, cutlure, out value))
                              sums[i] = (sums[i] == decimal.MinValue) ? value : sums[i] + value;
                      }
                      return sums;
                  },
                  sums => sums.Select(sum => (sum == decimal.MinValue) ? "N/A" : sum.ToString()).ToArray());
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2023-03-26
                • 1970-01-01
                • 1970-01-01
                • 2013-12-18
                • 1970-01-01
                • 2016-04-03
                • 1970-01-01
                相关资源
                最近更新 更多