使用LINQ遍历一个列表加一个值

问题描述 投票:0回答:2

在我正在实现的校验和计算算法中,输入必须是偶数个字节-如果不是,则必须在末尾打包一个额外的零字节。

我不想通过实际添加元素来修改输入数据到我的方法(并且输入可能是不可修改的)。我也不想创建新的数据结构并复制输入。

我想知道LINQ是否是创建类似以下内容的轻量级IEnumerable的好选择:

void Calculate(IList<byte> input)
{
 IEnumerable<byte> items = (input.Count & 1 ==0) ? items : X(input,0x0);
 foreach(var i in items)
 {
   ...
 } 
}

X(...)会是什么样?

c# linq
2个回答
1
投票

您可以使用此迭代器(yield return)扩展方法将额外的项目添加到IEnumerable<T>的末尾,而无需首先对元素进行迭代(您需要按顺序进行操作才能获得.Count值)。

请注意,应检查inputIReadOnlyCollection<T>还是IList<T>,因为这意味着可以提前知道.Count时可以使用更优化的代码路径。

public static IEnumerable<T> EnsureModuloItems<T>( this IEnumerable<T> source, Int32 modulo, T defaultValue = default )
{
    if( source is null ) throw new ArgumentNullException(nameof(source));
    if( modulo < 1 ) throw new ArgumentOutOfRangeException( nameof(modulo), modulo, message: "Value must be 1 or greater." );

    //

    Int32 count = 0;
    foreach( T item in source )
    {
        yield return item;
        count++;
    }

    Int32 remainder = count % modulo;
    for( Int32 i = 0; i < remainder; i++ )
    {
        yield return defaultValue;
    }  
}

使用方式如下:

foreach( Byte b in input.EnsureModuloItems( modulo: 2, defaultValue: 0x00 ) )
{

}

0
投票

您可能会为此使用Concat方法>>

Concat

我还对您的代码进行了一些更改,IEnumerable<byte> items = input.Count() % 2 == 0 ? input : input.Concat(new[] { (byte)0x0 }); 没有Count属性,您应该使用IEnumerable<T>方法。

由于Count()接受Concat(),因此需要IEnumerable<T> ao数组。您可以创建一个简单的扩展方法,将单个项目包装为List<T>

IEnumerable<T>

并使用它

internal static class Ext
{
    public static IEnumerable<T> Yield<T>(this T item)
    {
        yield return item;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.