结合多个列表中的信息

时间:2017-11-26 17:24:35

标签: c# arrays performance linq sorting

我有多个string[]定义如下:

var allEntities = new[] { "a", "b", "c", "d", "e", "f", "g", "h", "i" }
var entitiesWithPriority = new[] { "c", "d", "g" }
var entitiesWithIssue = new [] { "d", "h", "i" }
var entitiesWith... = new [] { ... }

现在我想通过使用以下类结构从这些数组中编译单个列表:

class Entity {
    public string Name { get; set; }
    public bool HasPriority { get; set; }
    public bool HasIssue { get; set; }
}

因此,操作的结果应该是这样的:

[
    { "name": "a", "hasPriority": false, "hasIssue": false }
    { "name": "b", "hasPriority": false, "hasIssue": false }
    { "name": "c", "hasPriority": true, "hasIssue": false }
    { "name": "d", "hasPriority": true, "hasIssue": true }
    { "name": "e", "hasPriority": false, "hasIssue": false }
    { "name": "f", "hasPriority": false, "hasIssue": false }
    { "name": "g", "hasPriority": true, "hasIssue": false }
    { "name": "h", "hasPriority": false, "hasIssue": true }
    { "name": "i", "hasPriority": false, "hasIssue": true }
]

我可以在以下代码中做一些事情,但我认为这个解决方案并不完美:

var result = allEntities.Select(entityName => new Entity()
{
    Name = entityName,
    HasPriority = entitiesWithPriority.Contains(entityName),
    HasIssue = entitiesWithIssue.Contains(entityName)
});

如何在提高效率的同时编译这样的列表。

3 个答案:

答案 0 :(得分:1)

您可以使用DictionaryHashsetAnyContains复杂度从O(n)降低到O(1)

上述想法仍可用于 large 列表,以替换list / array / IEnumarable<> Contains O(n) Hashset包含O(1)

var entitiesWithPriorityMap = entitiesWithPriority.ToDictionary(e => e.entityName, e => true);  
var entitiesWithIssueMap = entitiesWithIssue.ToDictionary(e => e.entityName, e => true);

var result = allEntities.Select(entityName => new Entity()
{
    Name = entityName,
    HasPriority = entitiesWithPriorityMap.ContainsKey(entityName),
    HasIssue = entitiesWithIssueMap.ContainsKey(entityName)
});

注意:这在处理Linq2Object和Linq2Sql时都有效(在这种情况下无法从Contains生成SQL)。

Hashset版本

var entitiesWithPriorityMap = new HashSet<Entity>(entitiesWithPriority);
var entitiesWithIssueMap = new HashSet<Entity>(entitiesWithIssue);

// replace ContainsKey with Contains

答案 1 :(得分:1)

你可以将他们加在一起:

var entities = 
     from name in allEntities
     join pr in entitiesWithPriority on name equals pr into np
     from priority in np.DefaultIfEmpty()
     join iss in entitiesWithIssue on name equals iss into npi
     from issue in npi.DefaultIfEmpty()
     select new Entity 
     { 
         Name = name, 
         HasPriority = !string.IsNullOrEmpty(priority), 
         HasIssue = !string.IsNullOrEmpty(issue)
     };

答案 2 :(得分:1)

首先创建一个dictionary <string>,<entity>并从所有实体填充它,所有hasXXX默认为false

之后,查找是O(1)

foreach (var key in EntitiesWithPriority)
{
   dict[key].hasPriority = true
}

等等