【问题标题】:Push a property value of an item in a List to next Item in that list将列表中项目的属性值推送到该列表中的下一个项目
【发布时间】:2015-06-20 13:23:35
【问题描述】:

我有两个对象说 Amount,NewAmount 都有以下属性

public class Amount
{
    public Int64 Id { get; set; }
    public Int64 Amt1 { get; set; }
    public Int64 Amt2 { get; set; }
} 
public class NewAmountDo
{
   public Int64 newAmt { get; set; }
}

我有一个包含一些值的 Amount 列表和一个包含一个值的 NewAmount 对象

List<Amount> amountListObject = new List<Amount>();
Amount amount = new Amount();
Amount amount1 = new Amount();
Amount amount2 = new Amount();
Amount amount3 = new Amount();
NewAmountDo newAmountDo = new NewAmountDo();
newAmountDo.newAmt = 50;
amount.Id = 1;
amount.Amt1 = 10;
amount.Amt2 = 100;
amountListObject.Add(amount);
amount1.Id = 2;
amount1.Amt1 = 20;
amount1.Amt2 = 200;
amountListObject.Add(amount1);
amount2.Id = 0;
amount2.Amt1 = 30;
amount2.Amt2 = 300;
amountListObject.Add(amount2);
amount3.Id = 0;
amount3.Amt1 = 40;
amount3.Amt2 = 400;
amountListObject.Add(amount3);

Console.WriteLine("Input ");
exising = amountListObject;

List<Amount> intermediate = new List<Amount>();
Amount newamount = new Amount();
intermediate.AddRange(amountListObject);
intermediate.Add(newamount);

我正在尝试将 NewAmount 对象的属性 newAmt 中的值添加到 amountListObject 的 Amt1 属性,并将 Amt1 的值下推到下一个列表项的 Amt1 值。但是我得到了列表中所有 Amt1 中第一个 Amt1 的值。下面是我试过的代码

for (int i = 0; i < intermediate.Count; i++)
{
    if (i == 0)
    {
       intermediate[i].Amt1 = newAmountDo.newAmt;
    }
    else
    {
       intermediate[i].Amt1 = exising[i - 1].Amt1;
    }
}

下面是输入:

Id : 1 , Amt1 : 10 , Amt2 : 100
Id : 2,  Amt1 : 20 , Amt2 : 200
Id : 0 , Amt1 : 30 , Amt2 : 300
Id : 0 , Amt1 : 40 , Amt2 : 400

下面是我得到的结果

Id : 1 , Amt1 : 50 , Amt2 : 100 
Id : 2 , Amt1 : 50 , Amt2 : 200
Id : 0 , Amt1 : 50 , Amt2 : 300
Id : 0 , Amt1 : 50 , Amt2 : 400
Id : 0 , Amt1 : 50 , Amt2 : 0

预期结果:

Id : 1 , Amt1 : 50 , Amt2 : 100
Id : 2 , Amt1 : 10 , Amt2 : 200
Id : 0 , Amt1 : 20 , Amt2 : 300
Id : 0 , Amt1 : 30 , Amt2 : 400
Id : 0 , Amt1 : 40, Amt2 : 0

有什么办法可以做到吗?

【问题讨论】:

    标签: c# list for-loop foreach


    【解决方案1】:

    首先为定义的类声明构造函数,它将有助于初始化并为代码提供更好的可读性。

    public class Amount
        {
            public Int64 Id { get; set; }
            public Int64 Amt1 { get; set; }
            public Int64 Amt2 { get; set; }
    
            public Amount(Int64 Id, Int64 Amt1, Int64 Amt2)
            {
                this.Id = Id;
                this.Amt1 = Amt1;
                this.Amt2 = Amt2;
            }
        }
        public class NewAmountDo
        {
            public Int64 newAmt { get; set; }
    
            public NewAmountDo(Int64 newAmt)
            {
                this.newAmt = newAmt;
            }
        }
    

    现在初始化会更干净:

    List<Amount> amountListObject = new List<Amount>();
    
    Amount amount = new Amount(1,10,100);
    Amount amount1 = new Amount(2,20,200);
    Amount amount2 = new Amount(0,30,300);
    Amount amount3 = new Amount(0,40,400);
    NewAmountDo newAmount = new NewAmountDo(50);
    amountListObject = new List<Amount>() { amount, amount1, amount2, amount3 };
    

    现在解决的问题:

    Int64 shiftedAmt = 0;
            for (int i = 0; i < amountListObject.Count; i++)
            {                
                /* First element in the list */
                if (i == 0)
                {
                    /* save the amt1 property value for shifting */
                    shiftedAmt = amountListObject[i].Amt1;
                    /* Switch to the new amount (if you need to add the new to the old just replace with +=) */
                    amountListObject[i].Amt1 = newAmount.newAmt;
                }
                else
                {
                    /* Shift the value */
                    Int64 temp = amountListObject[i].Amt1;
                    amountListObject[i].Amt1 = shiftedAmt;
                    shiftedAmt = temp;
                }
            }
            /* Create new Amount object for the last shifted amt1 value */
            Amount _amount = new Amount(0, shiftedAmt, 0);
            amountListObject.Add(_amount);
    

    【讨论】:

      【解决方案2】:

      问题是您在两个列表之间复制了 Amount 对象的引用。因此,当您将前一个元素中的金额复制到中间列表时,您基本上会覆盖您将在下一个循环中使用的值。

      我看到了 3 个解决您问题的方法:

      1. 为您的 Amount 类型使用 struct 而不是 class。这将执行值复制而不是参考副本,因此您不会在 2 个列表中拥有相同的实例,并且不会有任何冲突。

      2. 如果你真的需要你的类型是一个,你可以做一个复制构造函数并将你的项目复制到中间列表中,如下所示:

        intermediate.AddRange(amountListObject.Select(o => new Amount(o)));
        

        这样,您的列表中仍然会有引用,但每个引用将指向您类型 Amount 的不同实例,因此不会发生冲突。

      3. 如果你想避免任何对象的副本,那么你需要修改你的代码以在你的 foreach 中使用一个中间值来保持之前 Amount 中的值,如下所示:

        Int64 previous;
        for (int i = 0; i < intermediate.Count; i++)
        {
            if (i == 0)
            {
                previous = intermediate[i].Amt1;
                intermediate[i].Amt1 = newAmountDo.newAmt;
            }
            else
            {
                Int64 temp = intermediate[i].Amt1;
                intermediate[i].Amt1 = previous;
                previous = temp;
            }
        }
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-23
        • 1970-01-01
        • 2017-09-28
        • 2021-12-22
        • 1970-01-01
        • 2019-08-18
        • 2021-03-17
        相关资源
        最近更新 更多