基于LINQ的两个元素选择性地重新排序列表

时间:2018-04-19 09:13:56

标签: c# json linq generics

我有一个json对象,我需要通过重新排序父元素下的子元素来重新排列它:(当前obj):

"groupFields": [
    {
        "id": 1,
        "name": "Performance",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 2,
        "name": "Engagement",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 4,
        "name": "Websites",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 5,
        "name": "Apps",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 8,
        "name": "Clicks",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 9,
        "name": "Settings",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 10,
        "name": "Conversions",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 12,
        "name": "Page post",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 13,
        "name": "Messaging",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 14,
        "name": "Media",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 15,
        "name": "Awareness",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 16,
        "name": "On Facebook",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 17,
        "name": "Offline",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 18,
        "name": "Store visits",
        "parentId": 10,
        "parentName": "Conversions"
    }

是:(孩子们正在追随父母)

"groupFields": [
    {
        "id": 1,
        "name": "Performance",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 2,
        "name": "Engagement",
        "parentId": null,
        "parentName": null
    },
            {
        "id": 8,
        "name": "Clicks",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 12,
        "name": "Page post",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 13,
        "name": "Messaging",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 14,
        "name": "Media",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 15,
        "name": "Awareness",
        "parentId": 2,
        "parentName": "Engagement"
    },
    {
        "id": 9,
        "name": "Settings",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 10,
        "name": "Conversions",
        "parentId": null,
        "parentName": null
    },
    {
        "id": 4,
        "name": "Websites",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 5,
        "name": "Apps",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 16,
        "name": "On Facebook",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 17,
        "name": "Offline",
        "parentId": 10,
        "parentName": "Conversions"
    },
    {
        "id": 18,
        "name": "Store visits",
        "parentId": 10,
        "parentName": "Conversions"
    }

我正在考虑使用LINQ对它进行排序(如果它是解决方案),但我无法获得正确的结果, 最初,我尝试使用OrderBy(Id).ThenBy(ParentId)对集合进行排序,但我得不到我想要的。然后我想把它们分成两个不同的列表:

var parentList = new Collection<GroupField>();
var childList = new Collection<GroupField>();

foreach (var source in sources)
{
    if (source.ParentGroupId == null) parentList.Add(source);
    if (source.ParentGroupId.HasValue) childList.Add(source);
}
var query = childList.Where(p => parentList.Any(c => c.ParentGroupId == p.Id)).ToList();

我的解决方案都没有用。

2 个答案:

答案 0 :(得分:2)

以下代码应该可以解决问题。

var returnList = new List<GroupField>();
foreach (var source in sources.Where(s => s.ParentId == null).OrderBy(p => p.Id))
{
   returnList.Add(source);
   returnList.AddRange(sources.Where(s => s.ParentId != null && s.ParentId == source.Id).OrderBy(p => p.Id))
}

return returnList;

答案 1 :(得分:1)

使用GroupingJoin

查看以下版本
var allData = new List<GroupField>();

var parents = allData.Where(s => s.ParentId == null)
                 .OrderBy(p => p.Id);

var children = allData.Where(s => s.ParentId != null)
                  .GroupBy(p => p.ParentId);

var result = new List<GroupField>();

var finalResult =
parents.Join(children,
             p => p.Id, 
             c => c.Key,
(p,c) => 
{
    result.Add(p);
    result.AddRange(c.OrderBy(x => x.Id));
    return result;
});
  

工作原理

  1. 从完整集合中获取父数据
  2. 使用ParentId
  3. 对子数据进行分组
  4. 加入两个馆藏,最终结果将在finalResult
  5. 时间复杂度 - O(n)