私はしばらくの間、オブジェクトのプロパティに基づいてオブジェクトのリストと比較するソリューションを見つけるために失敗してきました。他の同様のソリューションを読みましたが、どちらも適切ではありませんでした(または私は答えを理解していませんでした!)。
コードはC#です
画像を表すモデルがあります
public class AccommodationImageModel
{
public int Id { get; set; }
public string Path { get; set; }
public string Caption { get; set; }
public string Description { get; set; }
public bool CoverImage { get; set; }
public bool Visible { get; set; }
}
このモデルの2つのリストがあります。 1つは既存のリスト、もう1つは更新されたリストです。 2つのリストを比較して、削除、更新、または新規のリストを確認する必要があります。
オブジェクト全体を比較する必要はありません。プロパティIDで比較するだけです。
List<AccommodationImageModel> masterList;
List<AccommodationImageModel> compareList;
CompareListにId = 0のAccommodationImageModelが含まれている場合、新しいエントリにはまだIDが割り当てられていないため、それらは新しいものです。
MasterListに、compareListにないIDを持つAccommodationImageModelが含まれている場合、それらは、compareListから削除されており、masterListから削除する必要があるため、削除されます。したがって、削除する必要があるもののリストが必要です。
NewListとmasterListに同じIDがある場合、それらは更新されます。したがって、同じIDを共有するもののリストが必要なので、それらを更新できます。これらのモデルが同一で、更新の必要がないかどうかはあまり心配していません。リストごとに数が少ないため、変更されていなくても更新されても問題はありません。
3つの結果のそれぞれをAccommodationImageModelのリストとして返す必要があるため、適切な更新、削除、追加を実行できます。
以下の3つのテスト方法を、ATMから選択したソリューションと共に追加し、実際の実装を示します。
[TestMethod]
public void Test_Deleted_Image()
{
// set up the masterList
List<AccommodationImageModel> masterList = new List<AccommodationImageModel>();
masterList.Add(new AccommodationImageModel { Id = 1 });
masterList.Add(new AccommodationImageModel { Id = 2 });
// set up the compare list
List<AccommodationImageModel> compareList = new List<AccommodationImageModel>();
compareList.Add(new AccommodationImageModel { Id = 1 });
compareList.Add(new AccommodationImageModel { Id = 3 });
compareList.Add(new AccommodationImageModel { Id = 0 });
// get the deleted models
List<AccommodationImageModel> result = masterList.Where(c => !compareList.Any(d => d.Id == c.Id)).ToList();
// result should hold first model with id 2
Assert.AreEqual(2, result.FirstOrDefault().Id);
}
[TestMethod]
public void Test_Added_Image()
{
// set up the masterList
List<AccommodationImageModel> masterList = new List<AccommodationImageModel>();
masterList.Add(new AccommodationImageModel { Id = 1 });
masterList.Add(new AccommodationImageModel { Id = 2 });
// set up the compare list
List<AccommodationImageModel> compareList = new List<AccommodationImageModel>();
compareList.Add(new AccommodationImageModel { Id = 1 });
compareList.Add(new AccommodationImageModel { Id = 3 });
compareList.Add(new AccommodationImageModel { Id = 0 });
// get the added models
List<AccommodationImageModel> result = compareList.Where(c => c.Id == 0).ToList();
// result should hold first model with id 0
Assert.AreEqual(0, result.FirstOrDefault().Id);
}
[TestMethod]
public void Test_Updated_Image()
{
// set up the masterList
List<AccommodationImageModel> masterList = new List<AccommodationImageModel>();
masterList.Add(new AccommodationImageModel { Id = 1 });
masterList.Add(new AccommodationImageModel { Id = 2 });
// set up the compare list
List<AccommodationImageModel> compareList = new List<AccommodationImageModel>();
compareList.Add(new AccommodationImageModel { Id = 1 });
compareList.Add(new AccommodationImageModel { Id = 3 });
compareList.Add(new AccommodationImageModel { Id = 0 });
// get the updated models
List<AccommodationImageModel> result = masterList.Where(c => compareList.Any(d => c.Id == d.Id)).ToList();
// result should hold first model with id 1
Assert.AreEqual(1, result.FirstOrDefault().Id);
}
シンプルなLinq
新着
List<AccommodationImageModel> new = compareList.Where(c=>c.id==0).ToList();
削除する
List<AccomodationImageModel> deleted = masterList.Where(c => !compareList.Any(d => c.id == d.id)).ToList();
更新する
List<AccomodationImageModel> toBeUpdated = masterList.Where(c => compareList.Any(d => c.id == d.id)).ToList();
同じId
を持つ2つのモデルが同じモデルと見なされるとすると、次のようにIEqualityComparer
を記述できます。
public class AccommodationImageModelComparer : IEqualityComparer<AccommodationImageModel>
{
public bool Equals(AccommodationImageModel x, AccommodationImageModel y)
{
if(x == null && y == null)
return true;
return x.Id == y.Id;
}
public int GetHashCode(AccommodationImageModel model)
{
return model.Id.GetHashCode();
}
}
次に、Linqを使用して必要なリストを取得できます。
var comparer = new AccommodationImageModelComparer();
var newItems = compareList.Where (l => l.Id == 0).ToList();
var toBeDeleted = masterList.Except(compareList, comparer).ToList();
var toBeUpdated = masterList.Intersect(compareList, comparer).ToList();
1つ目は、Id
が0のアイテムをフィルターするだけで、新しいアイテムと見なされます。 2番目のクエリは、masterList
にない項目をcompareList
に返します。最後のクエリは、両方のリストにあるアイテムを返します。 このコードはコンパイルされますが、テストされていません。
簡単な方法の1つは、your AccomodationImageModel
の_==
_演算子を次のようにオーバーライドすることです。
_public static override bool operator ==(AccommodationImageModel a, AccommodationImageModel b)
{
return a.Id == b.Id;
}
_
次に、比較する場合は、マスターリストを比較リストと照合して、比較リストに同一のオブジェクトがないマスターリストのリストを削除します。
_List<AccomodationImageModel> rem = new List<AccomodationImageModel>;
List<AccomodationImageModel> newobj = new List<AccomodationImageModel>;
foreach(AccomodationImageModel a in compareList) {
if(a.Id == 0) { // id == 0 => new item
newobj.Add(a); // add new item later
} else {
// check those existing items as to whether they need to be updated or removed
bool match = false;
foreach(AccomodationImageModel b in masterList) {
if(a == b) match = true; // match found
}
if(!match) rem.Add(a); else Update(a); // will be removed or updated
}
}
// now remove unmatched items
foreach(AccomodationImageModel a in rem) { masterList.Remove(a); }
foreach(AccomodationImageModel a in newobj) { AddNew(a); }
_
注Update(AccomodationImageModel a)
は特定のアイテムを更新するためのメソッドであり、AddNew(AccomodationImageModel a)
はマスターリスト内の新しいアイテムを挿入するためのメソッドです。
また、マスターリストからの削除とマスターリストへの挿入を行う必要があることに気付いたかもしれませんafterマスターリストをループしました!
///If image is not in list then add the image to the list
public void AddNew (List<AccomodationImageModel> masterList, AccomodationImageModel theImage)
{
masterList.Add(theImage);
}
/// If Image is in List then change listitem with new one
public void Update (List<AccomodationImageModel> masterList, int OldOnesID, AccomodationImageModel theNew)
{
masterList[OldOnesID] = theNew;
}
/// If Image should delete then removes the image from list
public void Delete (List<AccomodationImageModel> imgList, AccomodationImageModel theImageToDelete)
{
masterList.Remove(theImageToDelete);
}
/// this method checks the image state and do the work
public void CheckState (List<AccommodationImageModel> masterList, AccomodationImageModel theImage, bool deleteIt)
{
for(int i = 0; i < masterList.Count; i++)
{
if (deleteIt)
{
Delete(masterList, theImage);
}
else
{
if(theImage.ID == 0)
{
AddNew(masterList, theImage);
}
if(masterList[i].ID == theImage.ID)
{
Update(masterList, i, theImage);
}
}
}
2つのリストをマスターリストおよび一時リストとして使用する場合は、一時リストを反復して、各一時リスト項目でCheckStateメソッドを使用できます。
お役に立てれば..