C# 基于属性值将对象放入单独列表的最灵活方法

C# 基于属性值将对象放入单独列表的最灵活方法,c#,.net,linq,C#,.net,Linq,我有一个对象集合,我很好奇如何将它们分成两个列表——一个列表包含特定类型的所有内容,另一个列表包含其余内容。我想到的一种方法是: var typeXs = (from o in collectionOfThings where o.Type == "typeX" select o); var notTypeXs = (from o in collectionOfThings where o.Type != "typeX" select o); 另一种方法是循环收集内容,并根据if/else进行

我有一个对象集合,我很好奇如何将它们分成两个列表——一个列表包含特定类型的所有内容,另一个列表包含其余内容。我想到的一种方法是:

var typeXs = (from o in collectionOfThings where o.Type == "typeX" select o);
var notTypeXs = (from o in collectionOfThings where o.Type != "typeX" select o);
另一种方法是循环收集内容,并根据if/else进行分配


这两种方法都简单易读,但我只是想知道是否有更巧妙的方法?

您可以将第二部分改写为

coll.GroupBy(o => o.Type == "TypeX");
var notTypeXs = collectionOfThings.Except(typeXs);

你可以把第二部分改写成

var notTypeXs = collectionOfThings.Except(typeXs);

< >我不想对你进行优化,但我认为你应该只考虑一次迭代。< /P>
    // You can optimize this by specifying reasonable initial capacities.
List<TypedO> typeXs = new List<TypedO>();
List<TypedO> notTypeXs = new List<TypedO>();

foreach(TypedO o in list)
{
    (o.Type == "typeX" ? typeXs : notTypeXs).Add(o); // Yeah, I know.
}
//您可以通过指定合理的初始容量对其进行优化。
列表类型xs=新列表();
List notTypeXs=新列表();
foreach(列表中的TypedO o)
{
(o.Type==“typeX”?typeXs:notTypeXs)。添加(o);//是的,我知道。
}

(修正)

< P>我不想对你进行优化,但我认为你应该只考虑一次迭代。

    // You can optimize this by specifying reasonable initial capacities.
List<TypedO> typeXs = new List<TypedO>();
List<TypedO> notTypeXs = new List<TypedO>();

foreach(TypedO o in list)
{
    (o.Type == "typeX" ? typeXs : notTypeXs).Add(o); // Yeah, I know.
}
//您可以通过指定合理的初始容量对其进行优化。
列表类型xs=新列表();
List notTypeXs=新列表();
foreach(列表中的TypedO o)
{
(o.Type==“typeX”?typeXs:notTypeXs)。添加(o);//是的,我知道。
}

(已更正)

此示例应说明您的目标:

class MyObject
{
    public int n;
    public string t;
}
加载我的原始列表:

List<MyObject> allObjects = new List<MyObject>() {
    new MyObject() { n = 0, t = "x" },
    new MyObject() { n = 1, t = "y" },
    new MyObject() { n = 2, t = "x" },
    new MyObject() { n = 3, t = "y" },
    new MyObject() { n = 4, t = "x" }
};

var-typeXs=allObjects.Where(i=>i.t==“x”).ToList();
var notTypeXs=allObjects.Except(typeXs.ToList();
或者,您可以使用List.ForEach方法,该方法只迭代一次,因此理论上应优于其他两个选项。此外,它不需要引用LINQ库,这意味着它是.NET2.0安全的

var typeXs = new List<MyObject>();
var notTypeXs = new List<MyObject>();
allObjects.ForEach(i => (i.t == "x" ? typeXs : notTypeXs).Add(i));
var typeXs=newlist();
var notTypeXs=新列表();
ForEach(i=>(i.t==“x”?typeXs:notTypeXs.Add(i));

此示例应说明您的目标:

class MyObject
{
    public int n;
    public string t;
}
加载我的原始列表:

List<MyObject> allObjects = new List<MyObject>() {
    new MyObject() { n = 0, t = "x" },
    new MyObject() { n = 1, t = "y" },
    new MyObject() { n = 2, t = "x" },
    new MyObject() { n = 3, t = "y" },
    new MyObject() { n = 4, t = "x" }
};

var-typeXs=allObjects.Where(i=>i.t==“x”).ToList();
var notTypeXs=allObjects.Except(typeXs.ToList();
或者,您可以使用List.ForEach方法,该方法只迭代一次,因此理论上应优于其他两个选项。此外,它不需要引用LINQ库,这意味着它是.NET2.0安全的

var typeXs = new List<MyObject>();
var notTypeXs = new List<MyObject>();
allObjects.ForEach(i => (i.t == "x" ? typeXs : notTypeXs).Add(i));
var typeXs=newlist();
var notTypeXs=新列表();
ForEach(i=>(i.t==“x”?typeXs:notTypeXs.Add(i));

如果您不想浏览列表两次,那么:

    var collectionOfThings = new[] 
        {
            new Thing { Id = 1, Type = "typeX" },
            new Thing { Id = 2, Type = "typeY" },
            new Thing { Id = 3, Type = "typeZ" },
            new Thing { Id = 4, Type = "typeX" }
        };


    var query = (from thing in collectionOfThings
                 group thing by thing.Type == "typeX" into grouped
                 //orderby grouped.Key descending
                 select new
                 {
                     IsTypeX = grouped.Key,
                     Items = grouped.ToList()
                 }).ToList();

    var typeXs = query.Find(x => x.IsTypeX).Items;
    var notTypeXs = query.Find(x => !x.IsTypeX).Items;

如果您不想浏览列表两次,那么:

    var collectionOfThings = new[] 
        {
            new Thing { Id = 1, Type = "typeX" },
            new Thing { Id = 2, Type = "typeY" },
            new Thing { Id = 3, Type = "typeZ" },
            new Thing { Id = 4, Type = "typeX" }
        };


    var query = (from thing in collectionOfThings
                 group thing by thing.Type == "typeX" into grouped
                 //orderby grouped.Key descending
                 select new
                 {
                     IsTypeX = grouped.Key,
                     Items = grouped.ToList()
                 }).ToList();

    var typeXs = query.Find(x => x.IsTypeX).Items;
    var notTypeXs = query.Find(x => !x.IsTypeX).Items;

我将使用“OfType”链接表达式,大致如下:

var typeXs = collectionOfThigs.OfType<typeX>();
var notTypeXs = collectionOfThings.Except(typeXs);
var typeXs=collectionOfThigs.OfType();
var notTypeXs=除(typeXs)之外的所有内容的集合;
(包括其他答案除外)。但是,这确实假设您拥有类型,而不仅仅是类型字符串


此外,如果不做一次决定,可能会对性能造成影响(如果重要的话,使用拆分添加的if可能是一种方法),但除非性能有问题,否则我更喜欢清晰性。

我会使用“OfType”链接表达式,大致如下:

var typeXs = collectionOfThigs.OfType<typeX>();
var notTypeXs = collectionOfThings.Except(typeXs);
var typeXs=collectionOfThigs.OfType();
var notTypeXs=除(typeXs)之外的所有内容的集合;
(包括其他答案除外)。但是,这确实假设您拥有类型,而不仅仅是类型字符串


此外,如果不做一次决定,可能会受到性能惩罚(如果重要的话,使用拆分加法的if可能是一种方法),但除非性能有问题,否则清晰性是我的首选。

我不确定如何处理返回的IEnumerable我不确定如何处理返回的IEnumerable Hanks,我曾经想过:“另一种方法是循环收集东西,然后根据if/else分配。”如果我是多余的,我很抱歉。我只是不得不推荐这个选项,严格地说,我没有使用if或else.:)谢谢,我已经想到了:“另一种方法是循环收集内容,然后根据if/else进行分配。”如果我是多余的,很抱歉。我只是不得不推荐这个选项,严格地说,我没有使用if或else.:)我认为这是最干净、最有表现力的方式。我认为这是最干净、最有表现力的方式。第二个例子可能是最好的,但很好地给出了所有选项+1而且它只对集合进行一次迭代,其他两个选项实际上都必须对集合进行两次迭代,尽管它们可能编写得更优雅一些。第二个示例可能是最好的,但很好地给出了所有选项+1而且它只对集合进行一次迭代,其他两个选项实际上都必须对集合进行两次迭代,尽管它们可能编写得更优雅一些。