这完全在C#中,使用.NET 2.0。
我有两个对象列表。它们不是相关的对象,但确实有某些东西 可以比较的共同点,例如基于Guid的唯一标识符。这两个清单需要 被另一个包含Guid的列表过滤,这个列表可能与之匹配,也可能不匹配 ID包含在前两个列表中。
我已经考虑过将每个对象列表转换为“对象”并进行排序的想法 那,但我不确定一旦它被投射我将能够访问ID属性,我是 认为对两个列表进行排序的方法在知道什么时应该有些愚蠢 要排序的列表是。
引入每个对象列表的最佳方法是什么,以便可以仅使用ID来对列表进行排序?
答案 0 :(得分:15)
您应该让每个不同的对象实现一个通用接口。然后创建IComparer< T>对于该界面并在您的排序中使用它。
答案 1 :(得分:2)
好的,如果你有权修改你的原始类只是为了在那里添加界面,马修就把它发现了。我在这里有点疯狂,并使用2.0匿名代表定义了一个完整的解决方案。 (我想我已经沉迷于3.0 Lambda了;否则,如果我还在使用2005,我可能会在foreach循环中写出来。)
基本上,使用公共属性创建一个接口。让yoru两个类实现接口。创建一个作为接口的通用列表,将值转换并将其转换为新列表;删除任何不匹配的项目。
//Program Output:
List1:
206aa77c-8259-428b-a4a0-0e005d8b016c
64f71cc9-596d-4cb8-9eb3-35da3b96f583
List2:
10382452-a7fe-4307-ae4c-41580dc69146
97f3f3f6-6e64-4109-9737-cb72280bc112
64f71cc9-596d-4cb8-9eb3-35da3b96f583
Matches:
64f71cc9-596d-4cb8-9eb3-35da3b96f583
Press any key to continue . . .
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
//test initialization
List<ClassTypeA> list1 = new List<ClassTypeA>();
List<ClassTypeB> list2 = new List<ClassTypeB>();
ClassTypeA citem = new ClassTypeA();
ClassTypeB citem2 = new ClassTypeB();
citem2.ID = citem.ID;
list1.Add(new ClassTypeA());
list1.Add(citem);
list2.Add(new ClassTypeB());
list2.Add(new ClassTypeB());
list2.Add(citem2);
//new common list.
List<ICommonTypeMakeUpYourOwnName> common_list =
new List<ICommonTypeMakeUpYourOwnName>();
//in english, give me everything in list 1
//and cast it to the interface
common_list.AddRange(
list1.ConvertAll<ICommonTypeMakeUpYourOwnName>(delegate(
ClassTypeA x) { return (ICommonTypeMakeUpYourOwnName)x; }));
//in english, give me all the items in the
//common list that don't exist in list2 and remove them.
common_list.RemoveAll(delegate(ICommonTypeMakeUpYourOwnName x)
{ return list2.Find(delegate(ClassTypeB y)
{return y.ID == x.ID;}) == null; });
//show list1
Console.WriteLine("List1:");
foreach (ClassTypeA item in list1)
{
Console.WriteLine(item.ID);
}
//show list2
Console.WriteLine("\nList2:");
foreach (ClassTypeB item in list2)
{
Console.WriteLine(item.ID);
}
//show the common items
Console.WriteLine("\nMatches:");
foreach (ICommonTypeMakeUpYourOwnName item in common_list)
{
Console.WriteLine(item.ID);
}
}
}
interface ICommonTypeMakeUpYourOwnName
{
Guid ID { get; set; }
}
class ClassTypeA : ICommonTypeMakeUpYourOwnName
{
Guid _ID;
public Guid ID {get { return _ID; } set { _ID = value;}}
int _Stuff1;
public int Stuff1 {get { return _Stuff1; } set { _Stuff1 = value;}}
string _Stuff2;
public string Stuff2 {get { return _Stuff2; } set { _Stuff2 = value;}}
public ClassTypeA()
{
this.ID = Guid.NewGuid();
}
}
class ClassTypeB : ICommonTypeMakeUpYourOwnName
{
Guid _ID;
public Guid ID {get { return _ID; } set { _ID = value;}}
int _Stuff3;
public int Stuff3 {get { return _Stuff3; } set { _Stuff3 = value;}}
string _Stuff4;
public string Stuff4 {get { return _Stuff4; } set { _Stuff4 = value;}}
public ClassTypeB()
{
this.ID = Guid.NewGuid();
}
}
}
答案 2 :(得分:1)
仅使用.NET 2.0方法:
class Foo
{
public Guid Guid { get; }
}
List<Foo> GetFooSubset(List<Foo> foos, List<Guid> guids)
{
return foos.FindAll(foo => guids.Contains(foo.Guid));
}
如果您的课程没有实现通用界面,则必须分别为每种类型实施GetFooSubset
。
答案 3 :(得分:0)
我不确定我是否完全理解你想要的东西,但是你可以使用linq从列表中选择匹配的项目以及对它们进行排序。这是一个简单的示例,其中一个列表中的值在另一个列表上进行过滤并排序。
List<int> itemList = new List<int>() { 9,6,3,4,5,2,7,8,1 };
List<int> filterList = new List<int>() { 2, 6, 9 };
IEnumerable<int> filtered = itemList.SelectMany(item => filterList.Where(filter => filter == item)).OrderBy(p => p);
答案 4 :(得分:0)
我还没有机会使用AutoMapper,但是根据您的描述,您希望check it out。来自Jimmy Bogard的帖子:
AutoMapper约定
由于AutoMapper会变平,它会 寻找:
匹配属性名称
嵌套属性名称(Product.Name 通过假设a映射到ProductName PascalCase命名约定)
以“Get”开头的方法, 所以GetTotal()映射到Total
已有任何现有的类型地图 构造
基本上,如果你删除了所有的 “点”和“获取”,AutoMapper将 匹配属性名称。马上, AutoMapper在不匹配时不会失败 类型,但由于其他一些原因。
答案 5 :(得分:0)
然而,我并不完全确定你想要的最终结果......
如果要比较两种不同类型的属性,可以将属性名称和相应的值投影到两个词典中。并且利用该信息对属性值进行某种排序/差异。
Guid newGuid = Guid.NewGuid();
var classA = new ClassA{Id = newGuid};
var classB = new ClassB{Id = newGuid};
PropertyInfo[] classAProperties = classA.GetType().GetProperties();
Dictionary<string, object> classAPropertyValue = classAProperties.ToDictionary(pName => pName.Name,
pValue =>
pValue.GetValue(classA, null));
PropertyInfo[] classBProperties = classB.GetType().GetProperties();
Dictionary<string, object> classBPropetyValue = classBProperties.ToDictionary(pName => pName.Name,
pValue =>
pValue.GetValue(classB, null));
internal class ClassB
{
public Guid Id { get; set; }
}
internal class ClassA
{
public Guid Id { get; set; }
}
classAPropertyValue
Count = 1
[0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]}
classBPropetyValue
Count = 1
[0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]}
答案 6 :(得分:0)
本质上应该可以满足您的需求 - 但您最好使用linq
class T1
{
public T1(Guid g, string n) { Guid = g; MyName = n; }
public Guid Guid { get; set; }
public string MyName { get; set; }
}
class T2
{
public T2(Guid g, string n) { ID = g; Name = n; }
public Guid ID { get; set; }
public string Name { get; set; }
}
class Test
{
public void Run()
{
Guid G1 = Guid.NewGuid();
Guid G2 = Guid.NewGuid();
Guid G3 = Guid.NewGuid();
List<T1> t1s = new List<T1>() {
new T1(G1, "one"),
new T1(G2, "two"),
new T1(G3, "three")
};
List<Guid> filter = new List<Guid>() { G2, G3};
List<T1> filteredValues1 = t1s.FindAll(delegate(T1 item)
{
return filter.Contains(item.Guid);
});
List<T1> filteredValues2 = t1s.FindAll(o1 => filter.Contains(o1.Guid));
}
}