我有一个收藏品:
Collection<DateOfValues> collectionDateOfValues;
...
我得到一个DateOfValues实例 - 让我们说dateOfValuesNew并想要迭代集合并仅覆盖不同的值。
public class DateOfValues
{
{
this.Values = new Collection<SomeValue>();
}
public int id { get; set;}
public DateTime Start { get; set; }
public Collection<SomeValue> Values;
}
public class SomeValue
{
public int Id { get; set; }
public DateOfValues Date { get; set; }
public string Status { get; set; }
publi decimal StatusNumber { get; set; }
}
我做了什么:
if (dateOfValuesNew != null)
{
foreach (var dateOfValues in collectionDateOfValues)
{
if (dateOfValues.Id == dateOfValuesNew.Id)
{
// Here Im sure to find the dateOfValues Instance I will work with.
}
}
}
但是,如果我想将dateOfValues
与dateOfValuesNew
与foreach
进行比较,那就很难看了。
有没有更好的方法呢?
可以更改DateOfValues的Start
。这是最简单的部分 - 因为我可以简单地覆盖它。
困难的部分是比较SomeValue Collection
。每个SomeValue都可以更改Date
和Status
- 这也可以通过覆盖来解决。
但SomeValue Collection可以成为新的SomeValue,也可以删除。
例如,dateOfValues在SomeValue Collection中有3个SomeValue,而dateOfValuesNew将有4个或2个。
答案 0 :(得分:1)
有点棘手,但这有效:
class Program
{
static void Main(string[] args)
{
// Test
DateOfValues dov1 = new DateOfValues { Id = 1, Start = new DateTime(2011, 12, 01) };
dov1.AddSomeValue(1,"OK",2);
dov1.AddSomeValue(2,"Not OK",3);
dov1.AddSomeValue(3,"Not OK",4);
dov1.AddSomeValue(4,"Additional dov1",5);
DateOfValues dov2 = new DateOfValues { Id = 1, Start = new DateTime(2011, 12, 02) };
dov2.AddSomeValue(1, "OK", 2);
dov2.AddSomeValue(2, "Not OK", 4);
dov2.AddSomeValue(3, "OK", 1);
dov2.AddSomeValue(6, "Additional dov2", 15);
foreach (Tuple<SomeValue,SomeValue> difference in dov1.GetDifference(dov2))
{
if (difference.Item1 != null)
{
Console.WriteLine("Item1: Id:{0}; Status:{1}; Status Number:{2}",
difference.Item1.Id, difference.Item1.Status, difference.Item1.StatusNumber);
}
if (difference.Item2 != null)
{
Console.WriteLine("Item2: Id:{0}; Status:{1}; Status Number:{2}",
difference.Item2.Id, difference.Item2.Status, difference.Item2.StatusNumber);
}
Console.WriteLine("-------------------------------------------");
}
}
}
public class DateOfValues
{
public DateOfValues()
{
Values = new Collection<SomeValue>();
}
public int Id { get; set; }
public DateTime Start { get; set; }
public Collection<SomeValue> Values;
public void AddSomeValue(int id, string status, decimal statusNumber)
{
Values.Add(new SomeValue{Date = this,Id = id,Status = status,StatusNumber = statusNumber});
}
public IEnumerable<Tuple<SomeValue, SomeValue>> GetDifference(DateOfValues other)
{
IEnumerable<SomeValue> notMatching = Values.Where(v => !other.Values.Any(o => v.Equals(o)))
.Union(other.Values.Where(v=> !Values.Any(o=> v.Equals(o)))).Distinct();
return notMatching
.GroupBy(x => x.Id)
.Select(x =>
new Tuple<SomeValue, SomeValue>(
x.FirstOrDefault(y => y.Date == this), x.FirstOrDefault(y => y.Date == other)));
}
}
public class SomeValue : IEquatable<SomeValue>
{
public int Id { get; set; }
public DateOfValues Date { get; set; }
public string Status { get; set; }
public decimal StatusNumber { get; set; }
public bool Equals(SomeValue other)
{
return other.Id == Id && other.Status == Status && other.StatusNumber == StatusNumber;
}
}
输出:
Item1: Id:2; Status:Not OK; Status Number:3
Item2: Id:2; Status:Not OK; Status Number:4
-------------------------------------------
Item1: Id:3; Status:Not OK; Status Number:4
Item2: Id:3; Status:OK; Status Number:1
-------------------------------------------
Item1: Id:4; Status:Additional dov1; Status Number:5
-------------------------------------------
Item2: Id:6; Status:Additional dov2; Status Number:15
-------------------------------------------
修改强>
替代方案,您可以使用EqualityComparer:
public class DateOfValues
{
public DateOfValues()
{
Values = new Collection<SomeValue>();
}
public int Id { get; set; }
public DateTime Start { get; set; }
public Collection<SomeValue> Values;
public void AddSomeValue(int id, string status, decimal statusNumber)
{
Values.Add(new SomeValue { Date = this, Id = id, Status = status, StatusNumber = statusNumber });
}
public IEnumerable<Tuple<SomeValue, SomeValue>> GetDifference(DateOfValues other)
{
var notMatching = Values.Except(other.Values, new SomeValueComparer())
.Union(other.Values.Except(Values,new SomeValueComparer()));
return notMatching
.GroupBy(x => x.Id)
.Select(x =>
new Tuple<SomeValue, SomeValue>(
x.FirstOrDefault(y => y.Date == this), x.FirstOrDefault(y => y.Date == other)));
}
}
public class SomeValueComparer : IEqualityComparer<SomeValue>
{
public bool Equals(SomeValue x, SomeValue y)
{
return
x.Id == y.Id &&
x.Status == y.Status &&
x.StatusNumber == y.StatusNumber;
}
public int GetHashCode(SomeValue obj)
{
return obj.GetHashCode();
}
}
public class SomeValue
{
public int Id { get; set; }
public DateOfValues Date { get; set; }
public string Status { get; set; }
public decimal StatusNumber { get; set; }
public override int GetHashCode()
{
return string.Format("{0}{1}{2}",Id,Status,StatusNumber).GetHashCode();
// or a better method to get a hashcode
}
}