将列表中项目的属性值推送到该列表中的下一个项目

时间:2015-06-20 13:23:36

标签: c# list for-loop foreach

我有两个对象,例如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 Object中属性newAmt中的值添加到amountListObject的Amt1属性,并将Amt1的值下推到下一个listitem的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

有没有办法实现这个目标?

2 个答案:

答案 0 :(得分:1)

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

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

  1. Amount 类型使用结构而不是。这将进行值复制而不是参考副本,因此您不会在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;
        }
    }
    

答案 1 :(得分: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);