我有这样的1和0的列表:
var list = new List<int>{1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1}
Run Code Online (Sandbox Code Playgroud)
两个项目之间,只能是一个零.如何将该列表拆分为0的子列表?
换句话说:如果我有这样的字符串:string myString = "111011011110111111011101"那么很容易将它分成0个字符串.但如何用列表来做呢?这个例子shoudl产生这些子列表:
1,1,1
1,1
1,1,1,1
1,1,1,1,1,1
1,1,1
1
Run Code Online (Sandbox Code Playgroud)
那么有没有更好的方法然后将每个元素转换为字符串,加入它们并做我展示可以用字符串做什么?
Mar*_*age 10
您可以通过将输入序列转换为序列序列来解决您的问题,就像LINQ GroupBy一样.但是,在您的情况下,您正在对输入序列的更改进行分组.也许有可能将现有的LINQ运算符组合起来GroupBy,Zip并将其组合Skip成一些你想要的东西,但我认为创建一个迭代器块更容易(并且表现得更好),该迭代器块查看输入序列中的项目对:
static class EnumerableExtensions {
public static IEnumerable<IEnumerable<T>> GroupOnChange<T>(
this IEnumerable<T> source,
Func<T, T, Boolean> changePredicate
) {
if (source == null)
throw new ArgumentNullException("source");
if (changePredicate == null)
throw new ArgumentNullException("changePredicate");
using (var enumerator = source.GetEnumerator()) {
if (!enumerator.MoveNext())
yield break;
var firstValue = enumerator.Current;
var currentGroup = new List<T>();
currentGroup.Add(firstValue);
while (enumerator.MoveNext()) {
var secondValue = enumerator.Current;
var change = changePredicate(firstValue, secondValue);
if (change) {
yield return currentGroup;
currentGroup = new List<T>();
}
currentGroup.Add(secondValue);
firstValue = secondValue;
}
yield return currentGroup;
}
}
}
Run Code Online (Sandbox Code Playgroud)
GroupOnChange将获取输入序列中的项目并将它们分组为一系列序列.如果是,则启动新组changePredicate.
您可以使用GroupOnChange您根据需要精确地分割输入序列.然后,您必须使用删除作为值为零的组Where.
var groups = items
.GroupOnChange((first, second) => first != second)
.Where(group => group.First() != 0);
Run Code Online (Sandbox Code Playgroud)
如果输入是类实例并且您希望按该类的属性进行分组,则也可以使用此方法.然后,您必须相应地修改谓词以比较属性.(我知道你需要这个,因为你问了一个现在删除的问题,这个问题稍微复杂一点,输入序列不仅仅是数字,而是带有数字属性的类.)
您可以编写这样的扩展方法:
public static class Extensions
{
public static IEnumerable<IEnumerable<TSource>> Split<TSource>(this IEnumerable<TSource> source, TSource splitOn, IEqualityComparer<TSource> comparer = null)
{
if (source == null)
throw new ArgumentNullException("source");
return SplitIterator(source, splitOn, comparer);
}
private static IEnumerable<IEnumerable<TSource>> SplitIterator<TSource>(this IEnumerable<TSource> source, TSource splitOn, IEqualityComparer<TSource> comparer)
{
comparer = comparer ?? EqualityComparer<TSource>.Default;
var current = new List<TSource>();
foreach (var item in source)
{
if (comparer.Equals(item, splitOn))
{
if (current.Count > 0)
{
yield return current;
current = new List<TSource>();
}
}
else
{
current.Add(item);
}
}
if (current.Count > 0)
yield return current;
}
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
var list = new List<int>{1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1};
var result = list.Split(0);
Run Code Online (Sandbox Code Playgroud)
int c = 0;
var list = new List<int>{1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1};
var res = list
// split in groups and set their numbers
// c is a captured variable
.Select(x=>new {Item = x, Subgroup = x==1 ? c : c++})
// remove zeros
.Where(x=>x.Item!=0)
// create groups
.GroupBy(x=>x.Subgroup)
// convert to format List<List<int>>
.Select(gr=>gr.Select(w=>w.Item).ToList())
.ToList();
Run Code Online (Sandbox Code Playgroud)
您可以按下一个零的索引进行分组:
static void Main(string[] args)
{
var list = new List<int> { 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1 };
var result = list.Select((e, i) => new { Element = e, Index = i })
.Where(e => e.Element == 1)
.GroupBy(e => list.IndexOf(0, e.Index));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1196 次 |
| 最近记录: |