合并和排列2列表

时间:2017-02-22 07:34:31

标签: c# asp.net-mvc linq

以下是我的模特:

public class Test
{
    public int TestId { get; set; }
    public List<VariantsRank> VariantsRanks { get; set; }
}

public class VariantsRank
{
    public int VariantId { get; set; }
    public string Name { get; set; }
    public int Rank { get; set; }
}

我有一个现有的Test实例,其中包含VariantsRanks

的以下值
VariantId = 10, Name = "V1", Rank = 0
VariantId = 11, Name = "V2", Rank = 1

然后我需要合并以下VariantsRank

VariantId = 12, Name = "V3", Rank = 0
VariantId = 13, Name = "V4", Rank = 1

并增加Rank以产生以下输出

VariantId = 10, Name = "V1", Rank = 0
VariantId = 11, Name = "V2", Rank = 1
VariantId = 12, Name = "V3", Rank = 2
VariantId = 13, Name = "V4", Rank = 3

我使用以下正常工作的代码(List1是原始列表,List2是要合并的列表)

int highestOrder = (List1.VariantsRanks.Max(cpo => cpo.Rank)) + 1;
foreach (var rank in List2.VariantsRanks)
{
    var match = List1.VariantsRanks.FirstOrDefault(x => x.VariantId == rank.VariantId);
    if (match != null) // found
    {
        match.Rank = rank.Rank;
    }
    else
    {
        rank.Rank = highestOrder;
        highestOrder = highestOrder + 1;
        List1.VariantsRanks.Add(rank);
    }
}

然后我需要将以下VariantsRank合并到新列表中(请注意匹配的VariantId值,但它们的顺序相反)

VariantId = 13, Name = "V4", Rank = 0
VariantId = 12, Name = "V3", Rank = 1

以便输出

VariantId = 10, Name = "V1", Rank = 0
VariantId = 11, Name = "V2", Rank = 1
VariantId = 13, Name = "V4", Rank = 2
VariantId = 12, Name = "V3", Rank = 3

然而上面的代码输出

VariantId = 10, Name = "V1", Rank = 0
VariantId = 11, Name = "V2", Rank = 1
VariantId = 12, Name = "V3", Rank = 1
VariantId = 13, Name = "V4", Rank = 0

Rank值未正确递增

如何修改代码以确保未添加重复的VariantId,但增加Rank

1 个答案:

答案 0 :(得分:1)

您发现的是,在2合并中,您添加的项目的值与现有列表中的VariantId匹配。这意味着您点击了if块中的代码,该代码会将现有项的值重置为您发布的模型中Rank的值。

例如,在循环的第一次迭代中,match是包含VariantID = 13的现有项目,而您设置的Rank等于rank.Rank的值{ 0

您需要先删除现有列表中的所有匹配项,然后迭代已发布的值,更新其Rank并添加到集合中。

你的代码应该是

// Get the VariantId values of the list to be merged
var ids = List2.VariantsRanks.Select(x => x.VariantId);
// Remove any matches from the existing list
List1.VariantsRanks.RemoveAll(x => ids.Contains(x.VariantId));
// Calculate the current highest rank
int highestOrder = (List1.VariantsRanks.Max(x => x.Rank));
foreach (var rank in List2.VariantsRanks)
{
    // Update the rank
    rank.Rank = ++highestOrder; // pre-increment
    // Add to the existing list
    List1.VariantsRanks.Add(rank);
}

根据聊天中的评论,第二个列表可能包含需要插入第一个列表中间的项目,那么代码需要

// Get the VariantId's of the first and last items in the list to be merged
var firstID = List2.VariantsRanks.First().VariantId;
var lastID = List2.VariantsRanks.Last().VariantId;
// Get the indexers of those items in the original list
var firstIndex = List1.VariantsRanks.FindIndex(x => x.VariantId == firstID);
var lastIndex = List1.VariantsRanks.FindIndex(x => x.VariantId == lastID);
if (firstIndex > lastIndex) // in case they are in descending order
{
    var temp = lastIndex;
    lastIndex = firstIndex;
    firstIndex = temp;
}
// Remove matches from the original list
for (int i = firstIndex; i < lastIndex + 1; i++)
{
    List1.VariantsRanks.RemoveAt(firstIndex);
}
// Inset the items from the list to be merged
for(int i = 0; i < List2.VariantsRanks.Count; i++)
{
    List1.VariantsRanks.Insert(firstIndex + i, List2.VariantsRanks[i]);
}
/ Re-number the Rank
for(int i = 0; i < List1.VariantsRanks.Count; i++)
{
    List1.VariantsRanks[i].Rank = i;
}

注意,只有合并列表中VariantId的值是连续的(按升序或降序排列)时,上述内容才有效