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;
}
这是一个非常可怕的代码,但也可以随心所欲。基本上,我们跟踪每个列表索引,并有一个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