通过交替元素混合两个数组(拉链样式)

时间:2009-03-26 03:54:26

标签: algorithm

将两个数组(可能有不同大小)中的元素混合在一起的优雅算法是什么,以便从每个数组以交替方式绘制项目,并将剩余部分添加到结尾?

E.g。

阵列1 - A,B,C,D,E,F,G

数组2 - 1,2,3,4

混合阵列 - A,1,B,2,C,3,D,4,E,F,G

我更喜欢C#中的解决方案,但我应该能够以任何语言(甚至某种形式的伪代码)读取和转置解决方案。

不要担心空检查或任何其他边缘情况,我会处理这些。

6 个答案:

答案 0 :(得分:8)

你的意思是什么?

// naive/boring approach
int i = 0;
int m = 0;
while (i < a1.size() || i < a2.size()) {
    if (i < a1.size())
        mixed[m++] = a1[i];
    if (i < a2.size())
        mixed[m++] = a2[i];
    i++;
}

如果使用它,您可能希望将数组长度存储在变量中,这样您就不必继续调用size()方法(或者使用您使用的任何语言)。

答案 1 :(得分:2)

有一个函数可以在python docs中完全执行此操作,该函数适用于 n 数组

from itertools import *

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

我想出了另一个如果它们早点用完就会继续重复通过较短阵列的那个:

from itertools import *    

def repeatrobin(*iterables):
    cycles = cycle(map(cycle, iterables))
    stop = iter(xrange(max(map(len, iterables)) * len(iterables) - 1))
    for c in cycles:
       yield c.next()
       stop.next()

>>> list(repeatrobin(('A', 'B', 'C', 'D', 'E', 'F', 'G'), (1, 2, 3, 4)))
['A', 1, 'B', 2, 'C', 3, 'D', 4, 'E', 1, 'F', 2, 'G', 3]
>>> list(repeatrobin(('A', 'B', 'C', 'D', 'E'), (1, 2, 3), ('*',)))
['A', 1, '*', 'B', 2, '*', 'C', 3, '*', 'D', 1, '*', 'E', 2, '*']

答案 2 :(得分:1)

我只是在涉及C#,当我正在学习IEnumerable时,我想我会尝试用迭代器来解决这个问题。

TwoListMerger将两个列表作为参数。虽然在任一列表中都有一些值要处理,但它会在每个列表之间交替返回一个值。当一个或其他列表用完时,迭代器不会交替,有效地完成剩余列表的值。

    public static IEnumerable TwoListMerger( List<object> List1, List<object> List2 )
    {
        // Intialise two indices for the two lists
        int ListIndex1 = 0;
        int ListIndex2 = 0;

        // Begin zipper - List1 will provide the first value, then List2, etc.
        bool YieldFromList1 = true;

        // While values in either list remain...
        while ( ( ListIndex1 < List1.Count ) ||
                ( ListIndex2 < List2.Count ) )      
        {
            // If next value comes from List1...
            if ( YieldFromList1 )
            {
                // Yield from List1 if List2 exhausted( otherwise from List2 )
                YieldFromList1 = ( ListIndex2 >= List2.Count );
                yield return List1[ ListIndex1++ ];
            }
            // Next value comes from List2...
            else
            {
                // Yield from List1 if List1 not exhausted (otherwise from List2)
                YieldFromList1 = ( ListIndex1 < List1.Count );
                yield return List2[ ListIndex2++ ];
            }
        }

        // End iterator
        yield break;
    }


// Example usage (List1 and List2 are lists of integers)
List<object> MergedList = new List<object>( );
foreach ( object o in TwoListMerger( List1, List2 ) )
{
    MergedList.Add( o );
}

foreach ( object o in MergedList )
{
    Console.Write( "{0} ", o.ToString() );
}
Console.WriteLine( "}" );

答案 3 :(得分:1)

PHP 的功能(仅适用于索引数组):

function array_merge_alternating(&$array1, &$array2)
{
    $result = array();

    $count1 = count($array1);
    $count2 = count($array2);

    $i = 0;
    while (($i < $count1) || ($i < $count2))
    {
        if($i < $count1)
            array_push($result, $array1[$i]);
        if($i < $count2)
            array_push($result, $array2[$i]);

        $i++;
    }

    return $result;
}

感谢Ryan Graham!

答案 4 :(得分:0)

我看到O(N),N =较大集合的算法,因为你必须迭代所有条目。

答案 5 :(得分:0)

我现在真的很开心IEnumerator了!

    public static IEnumerable TwoListMerger( List<object> List1, List<object> List2 )
    {
        IEnumerator e1 = List1.GetEnumerator( );
        IEnumerator e2 = List2.GetEnumerator( );

        // Declare here (scope of while test)
        bool b1 = true;
        bool b2 = true;

        // While values remain in either list
        while ( b1 || b2 )
        {
            // NB assignments in "if"s return bool

            // If we have a value remaining in List1, yield return it
            if ( b1 && ( b1 = e1.MoveNext( ) ) )
                yield return e1.Current;

            // If we have a value remaining List2, yield return it
            if ( b2 && ( b2 = e2.MoveNext( ) ) )
                yield return e2.Current;            }

        // Done
        yield break;
    }