是否有系统集合类型在将不同大小的集合相互映射时自动处理环转



我有一个列的集合和一个整数的宽度集合,我想应用于它们。如何使它们彼此的大小独立?

假设我有列[col1, col2, col3, col4, col5]和宽度[10,15,20]结果应该是

col1: 10
col2: 15
col3: 20
col4: 10
col5: 15

对于[col1, col2][10,15,20]

col1: 10
col2: 15

我之前通过操作自定义类型列表中的索引(如 if (i == widths.Length()) {i=0}(手动做了类似的事情,但是系统类型或方法中是否有自动处理循环循环的内容?

你可以使用 modus

public static void CombineList()
{
    List<string> cols = new List<string> {"col1", "col2", "col3", "col4", "col5", "col6", "col7"};
    List<string> nums = new List<string> { "10", "20", "50"};
    int numsCount = nums.Count;
    List<string> comb = new List<string>();
    for(int i = 0; i < cols.Count; i++)
    {
        string s = $"{cols[i]}: {nums[i%numsCount]}";
        Debug.WriteLine(s);
        comb.Add(s);    
    }
    Debug.WriteLine("done");
}
col1: 10
col2: 20
col3: 50
col4: 10
col5: 20
col6: 50
col7: 10

如果您的集合已编制索引(例如使用 ArrayList(,那么您只需对列和权重集合使用模算术。要分配的权重类似于

列权重 = 权重[ 列索引 % # 权重]

您可以使用这样的函数,该函数将集合作为输入并返回它,以便重复其值,直到达到最小长度。

public static IEnumerable<T> RepeatToMinimumLength<T>(IEnumerable<T> input, 
    int minimumLength)
{
    var inputAsList = input as List<T> ?? input.ToList();
    if (inputAsList.Count >= minimumLength) 
        return inputAsList.Take(minimumLength);
    if (!inputAsList.Any()) 
        throw new ArgumentException("input must have at least one element.");
    var output = new List<T>(inputAsList);
    while(output.Count < minimumLength)
        output.AddRange(inputAsList);
    return output.Take(minimumLength);
}

您可以创建一个列表扩展来很好地处理它。称其为Expand方法或其他方法。请注意,它会修改原始数据,因此模%方法或创建返回新集合的方法总体上更安全。

public static class SomeListExtensions
{
    public static void Expand<T>( this List<T> list, int count )
    {
        if ( count < list.Count )
        {
            list.RemoveRange( count, list.Count - count );
        }
        else if ( count > list.Count )
        {
            int oldCount = list.Count;
            for ( int i = oldCount; i < count; i++ )
                list.Add( list[ i % oldCount ] );
        }
    }
}

以下代码返回10, 15, 20, 10, 15

class Program
{
    static void Main( string[] args )
    {
        List<int> values = new List<int>();
        values.Add( 10 );
        values.Add( 15 );
        values.Add( 20 );
        List<string> groups = new List<string>();
        groups.Add( "col1" );
        groups.Add( "col2" );
        groups.Add( "col3" );
        groups.Add( "col4" );
        groups.Add( "col5" );
        values.Expand( groups.Count );
        Console.WriteLine( string.Join( ", ", values ) );
    }
}

您要求对Enumerable.Zip进行专门的实现:

public static IEnumerable<TResult> ZipCycle<TSource1, TSource2, TResult>(
    this IEnumerable<TSource1> first,
    IEnumerable<TSource2> second,
    Func<TSource1, TSource2, TResult> selector)
{
    if (first == null)
        throw new ArgumentNullException(nameof(first));
    if (second == null)
        throw new ArgumentNullException(nameof(second));
    if (selector == null)
        throw new ArgumentNullException(nameof(selector));
    return InnerZip();
    IEnumerable<TResult> InnerZip()
    {
        using (var f = first.GetEnumerator())
        using (var s = second.GetEnumerator())
        {
            var firstIteration = true;
            while (f.MoveNext())
            {
                if (!s.MoveNext())
                {
                    if (firstIteration)
                    {
                        yield break;
                    }
                    else
                    {
                        s.Reset();
                        s.MoveNext();
                    }
                }
                yield return selector(f.Current, s.Current);
                firstIteration = false;
            }
        }
    }
}

这应该可以解决问题。

最新更新