0

所以我有一个“超级”列表:DestinationColumn,有 100 个字符串。为了简单起见,假设总是 100。

它来自几个源列,ColA、ColB。其中一些将有 100 个字符串,有些则更少。

所以,例如:

ColA 具有字符串 1-33、40-70 和 90-100 的值。它获得第一优先级,并将所有值填充到这些字符串的 DestinationColumn 中。ColB 具有 1-40 和 70-100 的值。在存在间隙的地方,它会填充它,但它不能覆盖 ColA 字符串。

现在我想确保这已经发生了。

列出 sourceColA、列出 sourceColB 和 ListdestinationColumn。

首先,我编写了一个函数来比较两个列表,看看它们是否包含相同的字符串:

public static bool ListEquals<T>(IList<T> list1, IList<T> list2)
    {
        if ((list1 == null) || (list2 == null))
        {
            return false;
        }
        if (list1.Count != list2.Count)
            return false;
        for (int i = list1.Count - 1; i >= 0; --i)
        {
            if (!list1[i].Equals(list2[i]))
            {
                return false;
            }
        }
        return true;
    }

现在我想保持它的通用性,但取 x 个源列,并确保所有内容现在都正确地位于一个目标列中。是否有这样做的一般模式?

我目前的想法是一个循环,根据destinationCol 标记ColA 的所有条目,对B 重复,等等,然后确保所有条目都没有被命中两次,并且所有条目都被命中一次。

4

2 回答 2

1

要按照您的描述合并两列,您可以这样做

ColA.Zip(ColB, (a, b) => a??b)

所以:

void Main()
{
    IEnumerable<IEnumerable<string>> cols=
        new string[][]
        {
            new string[]{"monkey", "frog", null, null, null, null},
            new string[]{null, null, null, null, "cat", "giraffe"},
            new string[]{null, null, null, "dog", "fish", null}
        };
    cols.MergeLeft().Dump();
    //gives: "monkey", "frog", null, "dog", "cat", "giraffe" 


}

static class Ex
{
    public static IEnumerable<T> MergeLeft<T>
        (this IEnumerable<IEnumerable<T>> cols) where T:class
    {
        var maxItems = cols.Max(x => x.Count());
        var leftMerged = 
            cols
                .Aggregate(
                    Enumerable.Repeat((T)null, maxItems),
                    (acc,col) => acc.Zip(col, (a, b) => a ?? b));
        return leftMerged;

    }
}

编辑

这是一个更有效的版本,MergeLeft不需要maxItems消除@Enigmativity 下面描述的费用:

static class Ex
{
    public static IEnumerable<T> MergeLeft<T>
        (this IEnumerable<IEnumerable<T>> cols) where T:class
    {
        return cols
            .Aggregate(
                Enumerable.Empty<T>(),
                (acc,col) => 
                acc
                    .Concat(Infinite<T>(null))
                    .Zip(col, (a, b) => a ?? b));   
    }
    private static IEnumerable<T> Infinite<T>(T item)
    {
        for(;;){yield return item;}
    }
}
于 2012-06-15T00:01:35.820 回答
0

我不完全确定我了解您要做什么,因为我不了解您的 ListEquals 的目的。无论如何,我会这样:

    public static void FillDest<T>(IList<T> dest, IList<IList<T>> srcLists)
        where T : class
    {
        bool goon = true;
        int idx = 0;
        dest.Clear();
        while (goon)
        {
            goon = false;
            bool added = true;
            foreach (IList<T> aSrc in srcLists)
            {
                added = false;
                T anItem;
                if (aSrc.Count <= idx)
                {
                    added = true;
                    continue;
                }
                goon = true;
                if ((anItem = aSrc[idx]) != null)
                {
                    dest.Add(anItem);
                    added = true;
                    break;
                }
            }
            if (!added)
                dest.Add((T)null);
            idx++;
        }
    }
于 2012-06-15T05:11:49.760 回答