Inverse IEnumerable.SelectMany?
本文关键字:SelectMany IEnumerable Inverse | 更新日期: 2023-09-27 18:02:44
是否存在IEnumerable.SelectMany
的逆/补?也就是说,是否存在一种形式为IEnumerable<T>.InverseSelectMany(Func<IEnumerable<T>,T>)
的方法,它将在输入序列中找到一个序列,并对单个元素进行转换,然后再次将整个元素平放?
例如,如果您想用单个字节的0x7E
替换HDLC帧中的所有转义序列{ 0x7E, 0x7E }
,您可以这样做
byte[] byteArray = new byte[] { 0x01, 0x02, 0x7E, 0x7E, 0x04 }; // etc.
byte[] escapeSequence = new byte[] { 0x7E, 0x7E };
byte[] outputBytes = byteArray.InverseSelectMany<byte,byte>(x =>
{
if (x.SequenceEqual(escapeSequence))
{
return new List<byte> { 0x7E };
{
else
{
return x;
}
});
这有什么意义吗?还是我遗漏了一些关键的东西?
没有这样的内置功能。第一个问题是,通过将任意的Func<IEnumerable<T>,T>
传递给枚举器,它将不知道需要"获取"多少字节并传递给函数。下面展示了一种更合理的方法,您可以传递一个要替换的序列,以及另一个要替换的序列,并对其进行简单的搜索。
public static class Extensions
{
public static IEnumerable<T> ReplaceSequence<T>(this IEnumerable<T> original, IEnumerable<T> toSearch, IEnumerable<T> toReplace) where T : IEquatable<T>
{
T[] toSearchItems = toSearch.ToArray();
List<T> window = new List<T>();
foreach (T value in original)
{
window.Add(value);
if (window.Count == toSearchItems.Length)
{
bool match = true;
for (int i = 0; i < toSearchItems.Length; i++)
{
if (!toSearchItems[i].Equals(window[i]))
{
match = false;
break;
}
}
if (match)
{
foreach (T toReplaceValue in toReplace)
{
yield return toReplaceValue;
}
window.Clear();
}
else
{
yield return window[0];
window.RemoveAt(0);
}
}
}
foreach (T value in window)
{
yield return value;
}
}
}
// http://stackoverflow.com/q/6751533/751090
public class StackOverflow_6751533
{
public static void Test()
{
byte[] byteArray = new byte[] { 0x01, 0x02, 0x7E, 0x7E, 0x04 };
byte[] escapeSequence = new byte[] { 0x7E, 0x7E };
byte[] unescapedSequence = new byte[] { 0x7E };
byte[] outputBytes = byteArray.ReplaceSequence(escapeSequence, unescapedSequence).ToArray();
for (int i = 0; i < outputBytes.Length; i++)
{
Console.Write("{0:X2} ", (int)outputBytes[i]);
}
Console.WriteLine();
}
}
我不知道这对其他人是否有帮助,但这是"逆"在我心里。例如,如果您有一个对象a。项目与 {1,2,3} 和 b。具有{3,4,5}的项调用DeselectMany将为您提供6个KeyValuePairs,分别为1:a, 2:a, 3:a, 3:b, 4:b, 5:b。你可以选择调用重载,让你返回KeyValuePair以外的东西
public static IEnumerable<KeyValuePair<TChild, TItem>> DeselectMany<TItem, TChild>(this IEnumerable<TItem> enumerable, Func<TItem, IEnumerable<TChild>> getElements)
{
return DeselectMany(
enumerable,
getElements,
(c, i) => new KeyValuePair<TChild, TItem>(c, i)
);
}
public static IEnumerable<TResult> DeselectMany<TItem, TChild, TResult>(this IEnumerable<TItem> enumerable, Func<TItem, IEnumerable<TChild>> getElements, Func<TChild, TItem, TResult> resultFactory)
{
foreach (var item in enumerable)
{
var elements = getElements(item);
foreach (var element in elements)
{
var result = resultFactory(element, item);
yield return result;
}
}
}