这是针对C# 3.5的
我尝试将ICollection拆分为单独的ICollections,其中的分隔符是一个序列。
例如
ICollection<byte> input = new byte[] { 234, 12, 12, 23, 11, 32, 23, 11 123, 32 };
ICollection<byte> delimiter = new byte[] {23, 11};
List<IICollection<byte>> result = input.splitBy(delimiter);会导致
result.item(0) = {234, 12, 12};
result.item(1) = {32};
result.item(2) = {123, 32};发布于 2011-06-21 03:45:36
private static IEnumerable<IEnumerable<T>> Split<T>
(IEnumerable<T> source, ICollection<T> delimiter)
{
// window represents the last [delimeter length] elements in the sequence,
// buffer is the elements waiting to be output when delimiter is hit
var window = new Queue<T>();
var buffer = new List<T>();
foreach (T element in source)
{
buffer.Add(element);
window.Enqueue(element);
if (window.Count > delimiter.Count)
window.Dequeue();
if (window.SequenceEqual(delimiter))
{
// number of non-delimiter elements in the buffer
int nElements = buffer.Count - window.Count;
if (nElements > 0)
yield return buffer.Take(nElements).ToArray();
window.Clear();
buffer.Clear();
}
}
if (buffer.Any())
yield return buffer;
}发布于 2011-06-21 06:01:02
最佳解决方案不是使用SequenceEqual()来检查每个子范围,否则您可能会为序列中的每个项目迭代分隔符的长度,这可能会影响性能,特别是对于较大的分隔符序列。可以在枚举源序列时对其进行检查。
这是我要写的,但总有改进的空间。我的目标是拥有与String.Split()相似的语义。
public enum SequenceSplitOptions { None, RemoveEmptyEntries }
public static IEnumerable<IList<T>> SequenceSplit<T>(
this IEnumerable<T> source,
IEnumerable<T> separator)
{
return SequenceSplit(source, separator, SequenceSplitOptions.None);
}
public static IEnumerable<IList<T>> SequenceSplit<T>(
this IEnumerable<T> source,
IEnumerable<T> separator,
SequenceSplitOptions options)
{
if (source == null)
throw new ArgumentNullException("source");
if (options != SequenceSplitOptions.None
&& options != SequenceSplitOptions.RemoveEmptyEntries)
throw new ArgumentException("Illegal option: " + (int)option);
if (separator == null)
{
yield return source.ToList();
yield break;
}
var sep = separator as IList<T> ?? separator.ToList();
if (sep.Count == 0)
{
yield return source.ToList();
yield break;
}
var buffer = new List<T>();
var candidate = new List<T>(sep.Count);
var sindex = 0;
foreach (var item in source)
{
candidate.Add(item);
if (!item.Equals(sep[sindex]))
{ // item is not part of the delimiter
buffer.AddRange(candidate);
candidate.Clear();
sindex = 0;
}
else if (++sindex >= sep.Count)
{ // candidate is the delimiter
if (options == SequenceSplitOptions.None || buffer.Count > 0)
yield return buffer.ToList();
buffer.Clear();
candidate.Clear();
sindex = 0;
}
}
if (candidate.Count > 0)
buffer.AddRange(candidate);
if (options == SequenceSplitOptions.None || buffer.Count > 0)
yield return buffer;
}发布于 2011-06-21 03:51:48
以下是我对此的看法:
public static IEnumerable<IList<byte>> Split(IEnumerable<byte> input, IEnumerable<byte> delimiter)
{
var l = new List<byte>();
var set = new HashSet<byte>(delimiter);
foreach (var item in input)
{
if(!set.Contains(item))
l.Add(item);
else if(l.Count > 0)
{
yield return l;
l = new List<byte>();
}
}
if(l.Count > 0)
yield return l;
}https://stackoverflow.com/questions/6416268
复制相似问题