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;
   }
});

这有什么意义吗?还是我遗漏了一些关键的东西?

Inverse IEnumerable.SelectMany?

没有这样的内置功能。第一个问题是,通过将任意的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;
            }
        }
    }