LINQ-合并2个列表,但有特定的顺序

本文关键字:顺序 合并 2个 列表 LINQ- | 更新日期: 2023-09-27 18:19:56

我想将两个列表合并为一个列表,但它必须按特殊顺序。

例如,我有一个类型a:的列表

{A,A,A、A、A……}

还有一个类型B:的列表

{B,B,B…}

期望的结果应该是这样的:

{A,A,B,A,A、B、A、A、B}

合并应该从列表A中取出2个项目,然后从列表B中取出1个项目。

需要注意的一点是,如果一个列表为空,请用第二个列表的项目填充所有其他项目。

我试图用LINQ找到一种优雅的方式。

这是我的代码,但它有点长,我希望有更好的方法通过linq:来完成它

非常感谢。

    public IList<PersonBase> Order(IList<Person1> people1, IList<Person2> people2)
    {
        if (people1.IsNullOrEmpty())
            return people2;
        if (people2.IsNullOrEmpty())
            return people1;
        List<PersonBase> orderedList = new List<PersonBase>();
        var people1Count = 0;
        var people2Count = 0;
        while (people2Count < people2.Count || people1Count < people1.Count)
        {
            var people1ToAdd = tags.Skip(people1Count).Take(1).ToList();
            people1Count = people1.Count();
            orderedList.AddRange(people1ToAdd);
            if (people1Count >= people1.Count)
            {
                orderedList.AddRange(people2.Skip(people2Count));
                break;
            }
            var people2ToAdd = people2.Skip(peopleCount).Take(2).ToList();
            people2Count = people2.Count();
            orderedList.AddRange(people2ToAdd);
            if (people2Count >= people2.Count)
            {
                orderedList.AddRange(people1.Skip(people1Count));
                break;
            }
        }
        return orderedList;
    }

LINQ-合并2个列表,但有特定的顺序

这是一个非常可怕的代码,但也可以随心所欲。基本上,我们跟踪每个列表索引,并有一个int来跟踪要使用哪个列表来填充结果数组。

List<int> list1 = new List<int>() { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
List<int> list2 = new List<int>() { 2, 2, 2, 2, 2 };
int list1Counter = 0;
int list2Counter = 0;
int arraychecker = 1;
int[] resultArray = new int[list1.Count + list2.Count];
for (int i = 0; i < resultArray.Length; i++)
{
    if (list1Counter < list1.Count && list2Counter < list2.Count)
    {
        if (arraychecker == 1 || arraychecker == 2)
        {
            resultArray[i] = list1[list1Counter];
            list1Counter++;
            arraychecker++;
        }
        else
        {
            resultArray[i] = list2[list2Counter];
            list2Counter++;
            arraychecker = 1;
        }
    }
    else if (list1Counter < list1.Count)
    {
        resultArray[i] = list1[list1Counter];
        list1Counter++;
    }
    else
    {
        resultArray[i] = list2[list2Counter];
        list2Counter++;
    }
}

您可以计算每个项目的索引,然后按该索引排序。

var mergedList =
    listA.Select((item, index) =>
        new { Index = index / 2 * 3 + (i % 2), Item = item})
    .Concat(listB.Select((item, index) =>
        new { Index = i * 3 + 2, Item = item}))
    .OrderBy(x => x.Index)
    .Select(x => x.Item)
    .ToList();

或者写一个方法。这更有效,因为它不需要排序;它只在每个列表中运行一次。

static IEnumerable<T> Alternate<T>(IEnumerable<T> sourceA, IEnumerable<T> sourceB) {
    using (IEnumerator<T> eA = sourceA.GetEnumerator(), eB = sourceB.GetEnumerator()) {
        bool aHasItems = true, bHasItems = true; 
        while (aHasItems || bHasItems) {
            if (eA.MoveNext()) yield return eA.Current;
            if (aHasItems = eA.MoveNext()) yield return eA.Current;
            if (bHasItems = eB.MoveNext()) yield return eB.Current;
        }
    }
}

这是我能做的最好的事情:

string[] test1 = { "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A" };
string[] test2 = { "B", "B" };
string[] result = test2.SelectMany((value, key) => test1.Skip(key * 2).Take(2).Concat(test2.Skip(key).Take(1))).ToArray();
        result = result.Concat(test1.Skip(result.Length / 3 * 2).Take(test1.Length - result.Length / 3 * 1)).ToArray();

这将从数组1中取2,然后从数组2中取1,再加上较长数组的剩余部分。输出:

AABAABAAAAAAAAA