2016-09-23 70 views
1

使用C#我試圖創建一個列表,其中包含多個元素添加新項目,如果主鍵不在列表中,否則更新項目if它確實如此。我已經發現了很多關於每個部分的內容,但是我一直在努力將其結合到我迄今爲止發現的可行解決方案中。C#更新多元素列表項目,如果項目已經存在,否則將其添加爲新項目

下面是編譯過的註釋代碼。

問題: 即使密鑰(ReceiptID)已經存在於列表中,因此解決方法是將所有項目添加爲新項目,以便我的檢查方式出現問題。

也許問題:(編輯:不是問題,因爲它按預期工作) 因爲我還沒有能夠測試更新如果存在的部分,我不知道我是否有這種權利。

任何指導表示讚賞。

編輯:(注意:根據WhoIsRich評論,這可能是使用字典而不是列表完成的,這可能會是一個更好,更有效的解決方案,謝謝WhoIsRich)。

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      IList<Receipts> receiptList = new List<Receipts>() 
      // The real app reads through a temporary table in the database 
      // to pick up the line items of a sale. The objective is to combine those line 
      // items into a summary list called receipts based on the receipt number. For this 
      // runnable example, I add some data to the receipt list here. 
      { 
       new Receipts() { ReceiptID = 1, TotalPrice = 10, TotalCost = 5, Profit = 5, EmployeeID = 1 }, 
       new Receipts() { ReceiptID = 2, TotalPrice = 15, TotalCost = 6, Profit = 9, EmployeeID = 1 }, 
       new Receipts() { ReceiptID = 3, TotalPrice = 20, TotalCost = 7, Profit = 13, EmployeeID = 1 }, 
       new Receipts() { ReceiptID = 4, TotalPrice = 25, TotalCost = 10.50M, Profit = 14.50M, EmployeeID = 1 }, 
      }; 
      // some dummy data to update list item with. Note: if receiptID is the same as one already in the list, employeeID 
      // will also be the same. (It's always the same employee that completes a whole transaction). 
      int[] receiptID = { 3, 4, 5, 5, 6, 7, 7, 8 }; 
      decimal[] totalPrice = { 5, 6, 7, 8, 9, 10, 11, 12 }; 
      decimal[] totolCost = { 2, 2.5M, 3, 3.5M, 4, 4.5M, 5, 5.5M }; 
      decimal[] profit = { 3, 3.5M, 4, 4.5M, 5, 5.5M, 6, 6.5M }; 
      int[] employeeID = { 1, 1, 1, 1, 2, 1, 1, 2 }; 

      // This for loop represents the while loop reading the database table 
      for (int i = 0; i < 8; i++) 
      { 
       // first, check to see if the receiptID is already in the list. This is the 
       // part I am having trouble with. 
       Receipts r = new Receipts(); 
//EDIT: 
      //if (receiptList.Contains(new Receipts { ReceiptID = receiptID[i] })) <== original in question 
      //if (receiptList.Any(rc => rc.ReceiptID == receiptID[i])) <== Keyur PATEL's comment to question - Works 
      //if (receiptList.Any(o => o.ReceiptID == receiptID[i])) <== kurakura88 answer - Works 
      if (receiptList.Any(receipt => receipt.ReceiptID == receiptID[i])) // <== Eric Wu - Works 

// END EDIT 
       { 
        // The code never enters here! <<=== This is what I need help with fixing 
        var tu = receiptList.Single(x => x.ReceiptID == receiptID[i]); 
        tu.TotalPrice += totalPrice[i]; 
        tu.TotalCost += totolCost[i]; 
        tu.Profit += profit[i]; 
        // receiptID and employeeID are not updated as they don't change in this if loop. 
       } 
       else 
       { 
        // This should happen if the receiptID is not in the list, but it's happening 
        // every time. 
        r.ReceiptID = receiptID[i]; 
        r.EmployeeID = employeeID[i]; 
        r.TotalPrice = totalPrice[i]; 
        r.TotalCost = totolCost[i]; 
        r.Profit = profit[i]; 
        receiptList.Add(r); 
       } 
      } 
      // Below here just displays the results in a sorted maner which is working ok. 
      var orderByValue = from s in receiptList 
           orderby s.ReceiptID 
           ascending 
           select s; 

      foreach (var item in orderByValue) 
      { 
       Console.WriteLine("Receipt: {0} Employee: {1} TotalPrice: {2} TotalCost: {3} Profit: {4}", item.ReceiptID.ToString(), item.EmployeeID.ToString(), item.TotalPrice.ToString(), item.TotalCost.ToString(), item.Profit.ToString()); 
      } 
      Console.ReadLine(); 
     } 
    } 

    public class Receipts 
    { 
     public int ReceiptID { get; set; } 
     public int EmployeeID { get; set; } 
     public decimal TotalPrice { get; set; } 
     public decimal TotalCost { get; set; } 
     public decimal Profit { get; set; } 
    } 

} 

/* 
The output I am getting is (note each sale line is added to list): 
Receipt: 1 Employee: 1 TotalPrice: 10 TotalCost: 5 Profit: 5 
Receipt: 2 Employee: 1 TotalPrice: 15 TotalCost: 6 Profit: 9 
Receipt: 3 Employee: 1 TotalPrice: 20 TotalCost: 7 Profit: 13 
Receipt: 3 Employee: 1 TotalPrice: 5 TotalCost: 2 Profit: 3 
Receipt: 4 Employee: 1 TotalPrice: 25 TotalCost: 10.50 Profit: 14.50 
Receipt: 4 Employee: 1 TotalPrice: 6 TotalCost: 2.5 Profit: 3.5 
Receipt: 5 Employee: 1 TotalPrice: 7 TotalCost: 3 Profit: 4 
Receipt: 5 Employee: 1 TotalPrice: 8 TotalCost: 3.5 Profit: 4.5 
Receipt: 6 Employee: 2 TotalPrice: 9 TotalCost: 4 Profit: 5 
Receipt: 7 Employee: 1 TotalPrice: 10 TotalCost: 4.5 Profit: 5.5 
Receipt: 7 Employee: 1 TotalPrice: 11 TotalCost: 5 Profit: 6 
Receipt: 8 Employee: 2 TotalPrice: 12 TotalCost: 5.5 Profit: 6.5 

What want to get is (same receiptID's should have values added together to one item in list): 
Receipt: 1 Employee: 1 TotalPrice: 10 TotalCost: 5 Profit: 5 
Receipt: 2 Employee: 1 TotalPrice: 15 TotalCost: 6 Profit: 9 
Receipt: 3 Employee: 1 TotalPrice: 25 TotalCost: 9 Profit: 16 
Receipt: 4 Employee: 1 TotalPrice: 31 TotalCost: 13 Profit: 18 
Receipt: 5 Employee: 1 TotalPrice: 15 TotalCost: 6.5 Profit: 8.5 
Receipt: 6 Employee: 2 TotalPrice: 9 TotalCost: 4 Profit: 5 
Receipt: 7 Employee: 1 TotalPrice: 21 TotalCost: 9.5 Profit: 11.5 
Receipt: 8 Employee: 2 TotalPrice: 12 TotalCost: 5.5 Profit: 6.5 
*/ 

編輯:糾正if語句之後,現在得到以下結果是正確的:

Receipt: 1 Employee: 1 TotalPrice: 10 TotalCost: 5 Profit: 5 
Receipt: 2 Employee: 1 TotalPrice: 15 TotalCost: 6 Profit: 9 
Receipt: 3 Employee: 1 TotalPrice: 25 TotalCost: 9 Profit: 16 
Receipt: 4 Employee: 1 TotalPrice: 31 TotalCost: 13.00 Profit: 18.00 
Receipt: 5 Employee: 1 TotalPrice: 15 TotalCost: 6.5 Profit: 8.5 
Receipt: 6 Employee: 2 TotalPrice: 9 TotalCost: 4 Profit: 5 
Receipt: 7 Employee: 1 TotalPrice: 21 TotalCost: 9.5 Profit: 11.5 
Receipt: 8 Employee: 2 TotalPrice: 12 TotalCost: 5.5 Profit: 6.5 
+1

List.Contains是失敗的地方,請考慮使用linq:'if(receiptList.Any(rc => rc.ReceiptID = receiptID [i]))' –

+0

它如何包含爲測試創建的Receipt對象? – Plutonix

+0

僅供參考:自定義類對象列表上的[.Contains())(http://stackoverflow.com/a/2629158/6741868)。它提到'.Contains()'必須被實現,或'.Equals()'被覆蓋,以便使用那些具有自定義類的類。 –

回答

2

答案是,即使同一類型的兩個對象不一定是相等的,他們具有相同的屬性。

因此,

receiptList.Contains(new Receipts { ReceiptID = receiptID[i] }) 

可能永遠是正確的。

如果你真的要檢查它在列表中,並且ReceiptIDID與您要檢查,然後做

receiptList.Any(receipt=>receipt.ReceiptID == receiptID[i]) 

Any()將檢查列表中的元素,並返回true如果有任何有條件地提供。

+0

感謝您對答案的解釋。這對我和其他人有用。 – Trevor