【问题标题】:How to loop through the properties of anonymous type in a list如何遍历列表中匿名类型的属性
【发布时间】:2020-06-20 11:43:10
【问题描述】:

如果我有以下 LINQ 查询:

 var outstandingDataTotalData = from t1 in dtTotal.AsEnumerable()
                                                  join t2 in dtOutstandingData.AsEnumerable() on
                                                   new
                                                   {
                                                       priv_code = t1["priv_code"],
                                                       pri_ded = t1["pri_ded"].ToString().Trim()
                               
                                                   } equals
                                                     new
                                                     {
                                                         priv_code = t2["priv_code"],
                                                         pri_ded = t2["pri_ded"].ToString().Trim()
               
                                                     }
                                                   into ps
                                                   from t2 in ps.DefaultIfEmpty()
                                                   select new
                                                   {
                                                       adjustment_value = t2 == null ? string.Empty : t2["adjustment_value"].ToString(),
                                                       amount_outstanding = t2 == null ? string.Empty : t2["amount_outstanding"].ToString(),
                                                       amount_outstanding_priv = t2 == null ? string.Empty : t2["amount_outstanding_priv"].ToString(),
                                                       amount_outstanding_ded = t2 == null ? string.Empty : t2["amount_outstanding_ded"].ToString(),
                                                       diff_outstanding = t2 == null ? string.Empty : t2["diff_outstanding"].ToString(),
                                                       exchange_rate = t2 == null ? string.Empty : t2["exchange_rate"].ToString(),
                                                       SalYear = t2 == null ? string.Empty : t2["sal_year"].ToString(),
                                                       SalMonth = t2 == null ? string.Empty : t2["sal_mon"].ToString()
                                                   };

现在outstandingDataTotalData 是一个匿名类型的列表。我有以下课程:

 public class AdjustmentTotal
    {
        public string SalYear { get; set; }

        public string SalMonth { get; set; }

        public string Value { get; set; }
    }

如何循环outstandingDataTotalData属性填充List<AdjustmentTotal>,如下例:

如果outstandingDataTotalData的结果集=

[0]{ adjustment_value = "100.00", amount_outstanding = "80.00", amount_outstanding_priv = "60.00", amount_outstanding_ded = "30.52", diff_outstanding = "0.36", exchange_rate = "", SalYear = "2018", SalMonth = "1" }

[1]{ adjustment_value = "1500.00", amount_outstanding = "5040.00", amount_outstanding_priv = "", amount_outstanding_ded = "", diff_outstanding = "0.36", exchange_rate = "", SalYear = "2018", SalMonth = "1" }

我想要List<AdjustmentTotal> 的结果集为:

2018  1   100.00
2018  1   1500.00
2018  1   80.00
2018  1   5040.00
2018  1   60.00
2018  1   
2018  1   30.52
2018  1   
2018  1   0.36
2018  1   0.36
2018  1
2018  1   

【问题讨论】:

  • 你试过outstandingDataTotalData .ToList<AdjustmentTotal>(); 吗?
  • @viveknuna 属性不一样
  • List 总计 =
  • 哦。我想我明白了;这就像将 N 个属性转换为一个属性的 N 行。你应该让你的生活变得轻松;首先不要将它们拉到属性中
  • 建议 - 如果您减少缩进,代码将适合屏幕。在 VS 和 SHIFT+TAB 中突出显示这些行。

标签: c# linq collections pivot anonymous-types


【解决方案1】:

让您的生活变得轻松,不要提取到单独的属性。将数据提取为数组:

select new {
  someArray = new[]{
    t2["adjustment_value"].ToString(),
    t2["amount_outstanding"].ToString(),       
    t2["amount_outstanding_priv"].ToString(),
    t2["amount_outstanding_ded"].ToString(),
    ...
  },
  SalYear = ...,

}

所以你最终得到一个具有 3 个属性的对象,两个字符串 SalXxx 和一个字符串数组(其他值)。字符串数组意味着您可以使用 LINQ SelectMany 将其展平。您将在 msdn 示例中看到,他们的所有者拥有宠物列表(宠物数量可变,但您的值是固定数量),并且在 selectmany 之后,它被展平为所有者重复且只有一只宠物的列表。您的小写值是宠物,SalXxx 值是所有者

一旦你得到一个有效的查询,你就可以将它集成到第一个查询中..

很抱歉没有发布完整的示例(为了清楚起见,我跳过了 null 检查)- 代码很难在手机上使用


编辑:

所以,您说您希望结果按特定顺序排列。 Select 和 SelectMany 都有一个版本,它们将提供项目的索引,我们可以使用它.. 因为您基本上想要拥有这些对象:

var obj = new [] { 
        new { SalYear = 2018, SalMonth = 1, C = new[] { "av1", "ao1", "aop1", "aod1" } }, 
        new { SalYear = 2018, SalMonth = 2, C = new[] { "av2", "ao2", "aop2", "aod2" } }
    };

就像av1, av2, ao1, ao2.. 所以我们想先按内部数组的索引对结果进行排序,然后再按外部数组的索引

我们使用 SelectMany 来挖掘内部数组,然后为内部数组中的每个项目创建一个新对象,该对象具有数据索引(内部和外部):

obj.SelectMany((theOuter, outerIdx) =>
  theOuter.C.Select((theInner, innerIdx) => 
    new { 
      SalYear = theOuter.SalYear, 
      SalMonth = theOuter.SalMonth, 
      DataItem = theInner, 
      OuterIdx = outerIdx,
      InnerIdx = innerIdx
    }
  )
).OrderBy(newObj => newObj.InnerIdx).ThenBy(newObj => newObj.OuterIdx)

您可能会发现您不需要 ThenBy;按 InnerIdx 排序会留下一个平局(我的列表中的每个 InnerIdx 都表示两次 - 有两个 innerIdx=0 等)并且 linq 中的东西尽可能地排序 - 因为它们已经按 OuterIdx 排序了(当他们去的时候进入查询)它们应该在与 InnerIdx 绑定后保持按 OuterIdx 排序。如果这是有道理的。腰带和牙套!

【讨论】:

  • 这里有个小问题,我想要t2["adjustment_value"],然后是第二个数组中的t2["adjustment_value"],然后是第二个数组中的`t2["amount_outstanding"]then t2["amount_outstanding"]`数组等等。这段代码解决了一半的问题
  • 我能说什么!你太棒了,太棒了。非常感谢你,我真的很感谢你的魔法。
【解决方案2】:
outstandingDataTotalData.Select(s => new AdjustmentTotal {
    SalYear = s.SalYear,
    SalMonth = s.SalMonth,
    Value = s.adjustment_value
}).ToList();

【讨论】:

    【解决方案3】:

    使用 eum :

        class Program
        {
    
            static void Main(string[] args)
            {
    
    
                List<AdjustmentTotal> totals = new List<AdjustmentTotal>();
                for (int i = 0; i < (int)VALUE.END; i++)
                {
                    foreach (var data in outstandingDataTotalData)
                    {
                        AdjustmentTotal total = new AdjustmentTotal();
                        totals.Add(total);
                        total.SalMonth = data.SalMonth;
                        total.SalYear = data.SalYear;
                        total._Type = (VALUE)i;
                        switch ((VALUE)i)
                        {
                            case VALUE.adjustment_value :
                                total.Value = data.adjustment_value;
                                break;
                            case VALUE.amount_outstanding:
                                total.Value = data.amount_outstanding;
                                break;
                            case VALUE.amount_outstanding_ded:
                                total.Value = data.mount_outstanding_ded;
                                break;
                            case VALUE.amount_outstanding_priv:
                                total.Value = data.amount_outstanding_priv;
                                break;
                            case VALUE.diff_outstanding:
                                total.Value = data.diff_outstanding;
                                break;
                            case VALUE.exchange_rate:
                                total.Value = data.exchange_rate;
                                break;
                        }
                    }
                }
            }
        }
        public enum VALUE
        {
            adjustment_value = 0, 
            amount_outstanding = 1, 
            amount_outstanding_priv = 2, 
            amount_outstanding_ded = 3, 
            diff_outstanding = 4, 
            exchange_rate = 5,
            END = 6
        }    
        public class AdjustmentTotal
        {
            public string SalYear { get; set; }
    
            public string SalMonth { get; set; }
    
            public string Value { get; set; }
    
            public VALUE _Type { get; set; }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多