C# 基于对象类型拆分对象列表

C# 基于对象类型拆分对象列表,c#,.net,linq,extension-methods,C#,.net,Linq,Extension Methods,我有如下对象列表——“Text1”、“Text2”、新的未定义信息(“Undfined1”)、新的未定义信息(“Undfined2”)、新的未定义信息(“undfined3”)、“Text3” 我需要如下输出: 输出 //列表> 0–文本1、文本2 1–未定义1、未定义2、未定义3 2–文本3 我设法写了下面的函数,这是坏的,但不知何故工作良好。是否有任何方法可以使用LINQ扩展实现同样的效果-TakeWhile或SkipWhile或使用yield。非常感谢您的帮助: public static

我有如下对象列表——“Text1”、“Text2”、新的未定义信息(“Undfined1”)、新的未定义信息(“Undfined2”)、新的未定义信息(“undfined3”)、“Text3”

我需要如下输出:

输出 //列表> 0–文本1、文本2 1–未定义1、未定义2、未定义3 2–文本3

我设法写了下面的函数,这是坏的,但不知何故工作良好。是否有任何方法可以使用LINQ扩展实现同样的效果-TakeWhile或SkipWhile或使用yield。非常感谢您的帮助:

public static List<List<object>> PartitionByTypes(List<object> values)
{
List<List<object>> partitionedList = new List<List<object>>();

        int j;
        for (int i = 0; i < values.Count; i++)
        {
            j = i;
            List<object> subList = new List<object>();
            Type t = values[j].GetType();
            do
            {
                subList.Add(values[j]);
                j++;
                if (j == values.Count)
                {
                    break;
                }
            } while (values[j].GetType() == t);
            partitionedList.Add(subList);
            i = j - 1;
        }

        return partitionedList;
    }
公共静态列表分区类型(列表值)
{
List partitionedList=新列表();
int j;
for(int i=0;i
好吧,你可以用LINQ和TakeWhile做到这一点,但我怀疑这会比普通的foreach更好。例如:

public static List<List<object>> LinqPartitionByTypes(List<object> values)
{
    var batches = new List<List<object>>();
    while (true)
    {
         object prev = null;
         var batch = values.Skip(batches.Sum(c => c.Count)).TakeWhile(c => {
              var result = prev == null || prev.GetType() == c.GetType();
              prev = c;
              return result;
         }).ToList();
         if (batch.Count == 0)
              break;
         batches.Add(batch);
     }
     return batches;
}
公共静态列表LinqPartitionByTypes(列表值)
{
var batches=新列表();
while(true)
{
object prev=null;
var batch=values.Skip(batches.Sum(c=>c.Count)).TakeWhile(c=>{
var result=prev==null | | prev.GetType()==c.GetType();
prev=c;
返回结果;
}).ToList();
如果(batch.Count==0)
打破
批次。添加(批次);
}
退货批次;
}
不过,我最好做一些更简单、更干净的事情:

public static List<List<object>> PartitionByTypes(List<object> values) {
    var batches = new List<List<object>>();
    object prev = null;
    var batch = new List<object>();
    foreach (var value in values) {
        if (prev != null && prev.GetType() != value.GetType()) {
            batches.Add(batch);
            batch = new List<object>();
        }
        batch.Add(value);
        prev = value;
    }
    if (batch.Count > 0)
        batches.Add(batch);

    return batches;
}
公共静态列表分区类型(列表值){
var batches=新列表();
object prev=null;
var batch=新列表();
foreach(值中的var值){
if(prev!=null&&prev.GetType()!=value.GetType()){
批次。添加(批次);
批次=新列表();
}
批量增加(价值);
prev=值;
}
如果(batch.Count>0)
批次。添加(批次);
退货批次;
}

以下内容将使用
yield
实现您想要的功能。因此,返回值将改为
IEnumerable

public static IEnumerable<List<object>> PartitionByTypes(List<object> values)
{
    Type prevType = null;
    List<object> cache = new List<object>();
    foreach (var value in values)
    {
        if(prevType != null && value.GetType() != prevType)
        {
            yield return cache;
            cache = new List<object>();
        }

        cache.Add(value);
        prevType = value.GetType();
    }

    if(cache.Count > 0)
        yield return cache;
}
公共静态IEnumerable分区类型(列表值)
{
类型prevType=null;
列表缓存=新列表();
foreach(值中的var值)
{
if(prevType!=null&&value.GetType()!=prevType)
{
产生返回缓存;
缓存=新列表();
}
cache.Add(value);
prevType=value.GetType();
}
如果(cache.Count>0)
产生返回缓存;
}
或者,您可以使用以下Linq查询

public static IEnumerable<List<object>> PartitionByTypes(List<object> values)
{
    int count = 0;
    return values.Select((o, i) => new 
        { 
            Object = o, 
            Group = (i == 0 || o.GetType() == values[i - 1].GetType()) ? count : ++count 
        })
        .GroupBy(x => x.Group)
        .Select(g => g.Select(x => x.Object).ToList());
}
公共静态IEnumerable分区类型(列表值)
{
整数计数=0;
返回值。选择((o,i)=>new
{ 
对象=o,
组=(i==0 | | o.GetType()==value[i-1].GetType())?计数:++count
})
.GroupBy(x=>x.Group)
.Select(g=>g.Select(x=>x.Object).ToList());
}
静态类型GetObjectTypeOrNull(对象o)
{
返回o==null?null:o.GetType();
}
静态IEnumerable分区类型(列表值)
{
如果(value==null)抛出新的ArgumentNullException(“值”);
如果(values.Count==0)产量中断;
类型currentType=GetObjectTypeOrNull(值);
列表缓冲区=新列表();
foreach(值中的对象值)
{
类型valueType=GetObjectTypeOrNull(值);
如果(valueType!=currentType)
{
currentType=valueType;
收益返回缓冲区;
buffer=新列表();
}
currentType=valueType;
缓冲区。添加(值);
}
如果(buffer.Count>0)
{
收益返回缓冲区;
}
}
示例:

List<object> input = new List<object> { "Text1", "Text2", new UndefinedInfo("Undefined1"), new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" };
PartitionByTypes(input).ToList();
List<object> input = new List<object> { null, "Text1", "Text2", null, null, new UndefinedInfo("Undefined1"), null, null, new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" };
PartitionByTypes(input).ToList();
List input=new List{“Text1”、“Text2”、new UndefinedInfo(“Undefined1”)、new UndefinedInfo(“Undefined2”)、new UndefinedInfo(“Undefined3”)、“Text3”};
PartitionByTypes(输入).ToList();
结果:

{ List<object>(2) { "Text1", "Text2" }, List<object>(3) { [Undefined1], [Undefined2], [Undefined3] }, List<object>(1) { "Text3" }
{List(2){“Text1”,“Text2”},List(3){[Undefined1],[Undefined2],[Undefined3]},List(1){“Text3”}
另一个示例-带有空值:

List<object> input = new List<object> { "Text1", "Text2", new UndefinedInfo("Undefined1"), new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" };
PartitionByTypes(input).ToList();
List<object> input = new List<object> { null, "Text1", "Text2", null, null, new UndefinedInfo("Undefined1"), null, null, new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" };
PartitionByTypes(input).ToList();
List input=new List{null,“Text1”,“Text2”,null,null,new UndefinedInfo(“Undefined1”),null,null,new UndefinedInfo(“Undefined2”),new UndefinedInfo(“Undefined3”),“Text3”};
PartitionByTypes(输入).ToList();
结果:

List<object>(1) { null }, List<object>(2) { "Text1", "Text2" }, List<object>(2) { null, null }, List<object>(1) { [Undefined1] }, List<object>(2) { null, null }, List<object>(2) { [Undefined2], [Undefined3] }, List<object>(1) { "Text3" }
List(1){null},List(2){“Text1”,“Text2”},List(2){null,null},List(1){[Undefined1]},List(2){null,null},List(2){[Undefined2],[Undefined3]},List(1){“Text3”}

试试这个:string output=string.Join(“,”,partitionedList.Select(x=>x.ToString()).ToArray());我终于在填充partitionedList了。你的解决方案将如何工作?你能提供示例输入和输出吗?你的输出是一个CSV字符串(每个数组项用逗号分隔)我的代码只是在列表中枚举,将每个项转换为字符串,然后使用字符串连接方法在每个项之间加上逗号。我想我应该使用一个值,而不是partitionList。请注意,除非列表以某种方式按类型排序,否则这不会将同一类型的所有实例分组在一个批中。据我所知s整点-将所有相同类型的连续对象拆分为单独的组。在第一个方法中,您忘记了
返回批;
。实际上,它的行为与OP的当前方法相同。我的注释只是一个注释。:@KhaledNassar…BTW…。谁是OP?:)这将跳过输入列表的最后一个元素,即返回列表共2人lists@Abhay我用
if(cache.Count>0)yield return cache;
修复了这个问题。谢谢@alex.b提供的空示例