我有以下对象列表 - “Text1”,“Text2”,新的UndefinedInfo(“Undfined1”),新的UndefinedInfo(“Undfined2”),新的UndefinedInfo(“Undefined3”),“Text3”
我需要输出如下:
输出 //列表> 0 - Text1,Text2 1 - 未定义1,未定义2,未定义3 2 - Text3
我设法写下面的功能很糟糕,但不知何故工作正常。有没有办法使用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;
}
答案 0 :(得分:2)
以下内容将使用yield
执行您想要的操作。因此,返回将是IEnumerable<List<object>>
。
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;
}
或者,您可以使用以下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());
}
答案 1 :(得分:0)
你可以用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;
}
但是,我最好做一些更简单,更干净的事情:
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;
}
答案 2 :(得分:0)
static Type GetObjectTypeOrNull(object o)
{
return o == null ? null : o.GetType();
}
static IEnumerable<List<object>> PartitionByTypes(List<object> values)
{
if (values == null) throw new ArgumentNullException("values");
if (values.Count == 0) yield break;
Type currentType = GetObjectTypeOrNull(values);
List<object> buffer = new List<object>();
foreach (object value in values)
{
Type valueType = GetObjectTypeOrNull(value);
if (valueType != currentType)
{
currentType = valueType;
yield return buffer;
buffer = new List<object>();
}
currentType = valueType;
buffer.Add(value);
}
if (buffer.Count > 0)
{
yield return buffer;
}
}
示例:强>
List<object> input = new List<object> { "Text1", "Text2", new UndefinedInfo("Undefined1"), new UndefinedInfo("Undefined2"), new UndefinedInfo("Undefined3"), "Text3" };
PartitionByTypes(input).ToList();
结果:
{ List<object>(2) { "Text1", "Text2" }, List<object>(3) { [Undefined1], [Undefined2], [Undefined3] }, List<object>(1) { "Text3" }
另一个例子 - 使用nulls:
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<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" }