【发布时间】:2018-08-11 05:41:39
【问题描述】:
我需要知道实现上述结果的最佳方法是什么:
我有以下课程:
public class Log
{
public HashSet<string> Ids { get; set; }
public string UniqueId { get; set; }
}
public class GroupModel
{
public List<Log> Logs { get; set; }
}
数据集如下:
GroupModel webApiGroupModel = new GroupModel()
{
Logs = new List<Log>()
{
new Log()
{
Ids = new HashSet<string>(){"a","g"},
UniqueId = "1"
},
new Log()
{
Ids = new HashSet<string>(){"b", "c" },
UniqueId = "2"
},
new Log()
{
Ids = new HashSet<string>(){"a", "b"},
UniqueId = "3"
},
new Log()
{
Ids = new HashSet<string>(){"e"},
UniqueId = "4"
},
new Log()
{
Ids = new HashSet<string>(){ "d", "e" },
UniqueId = "5"
},
new Log()
{
Ids = new HashSet<string>(){ "f"},
UniqueId = "6"
},
new Log()
{
Ids = new HashSet<string>(){ "g"},
UniqueId = "7"
},
new Log()
{
Ids = new HashSet<string>(){ "a", "g" },
UniqueId = "8"
},
new Log()
{
Ids = new HashSet<string>(){ "h", "e","g" },
UniqueId = "9"
},
new Log()
{
Ids = new HashSet<string>(){ },//Intentionally left blank
UniqueId = "10"
},
}
};
我需要根据相关的 Id 对它们进行分组,所以结果将如下所示:
Group1 = UniqueId 为 1,2,3,4,5,7,8,9 的列表
Group2 = 唯一 ID 为 6 的列表
Group3 = 唯一 ID 为 10 的列表
说明:
Group1:如果任何 Log 与任何 Ids 项匹配,则它们必须组合为一个。由于具有唯一 ID 1 的日志具有 ID“a,g”,这些 ID 存在于具有唯一 ID 3、7、8、9 的日志中,因此这些被组合,但是还有 3、7、8、9 其他项目,即“b,e”,它们是存在于 2 , 4, 5 中,因此所有这些都被分组,即 1,2,3,4,5,7,8,9
Group2,3 Id 不存在于任何日志中,因此它们位于唯一的组中。
我试图以最好的方式实现这一点,因为我使用的解决方案需要 2 分钟才能将数据集与 25K 日志进行分组,这非常糟糕。 每个 Log 中的最大可能 Id 可以是 3。
以下是我的解决方案,您可以帮助我优化它或提供完全不同的方法来实现上述结果。
private static ICollection<List<Log>> GroupIds(List<Log> logs)
{
Dictionary<int, HashSet<string>> tempgroupedIds = new Dictionary<int, HashSet<string>>();
HashSet<string> UniqueIds = new HashSet<string>();
HashSet<string> tempgroupedIds2 = new HashSet<string>();
int id = 1;
foreach (var log in logs)
{
List<int> tempGroupNames = new List<int>();
foreach (var Id in log.Ids)
{
if (!string.IsNullOrEmpty(Id))
{
UniqueIds = new HashSet<string>(logs
.Where(d => d.Ids.Contains(Id)).Select(p => p.UniqueId));
var OtherLogsContainingUniqueIds = tempgroupedIds
.Where(d => UniqueIds != null && d.Value.Intersect(UniqueIds).Any())
.Select(d => d.Key);
if (OtherLogsContainingUniqueIds.Any())
{
tempGroupNames.AddRange(OtherLogsContainingUniqueIds.ToList());
}
}
if (tempGroupNames.Any())
{
var tempCorelationids = new HashSet<string>(tempgroupedIds.Where(d => tempGroupNames.Contains(d.Key)).SelectMany(a => a.Value));
tempCorelationids.UnionWith(UniqueIds);
foreach (var groupname in tempGroupNames)
{
//If id is found in exiting group put all the Ids from this group to the existing group and remove this group
tempgroupedIds.Remove(groupname);
}
tempgroupedIds2.UnionWith(UniqueIds);
tempgroupedIds.Add(id, tempCorelationids);
id++;
}
else
{
// This a unique group untill some other log is found containing this Id
tempgroupedIds2.UnionWith(UniqueIds);
tempgroupedIds
.Add(id, UniqueIds);
id++;
}
}
}
ICollection<List<Log>> finalGroup = new Collection<List<Log>>();
foreach (var groupedlogKey in tempgroupedIds)
{
var group = logs
.Where(a => groupedlogKey.Value.Contains(a.UniqueId)).ToList();
finalGroup.Add(group);
}
//With empty Ids
var anonymousLogs = logs
.Where(a => !tempgroupedIds2.Contains(a.UniqueId)).ToList();
if (anonymousLogs.Count >= 1)
{
finalGroup.Add(anonymousLogs);
}
return finalGroup;
}
}
【问题讨论】:
-
如果你能用你尝试过的代码更新问题,我会更好
-
是的,到目前为止你的解决方案是什么,所以我们知道不会给你同样的解决方案
-
另外,如果我们不知道你在做什么,我们将如何比较速度
-
当然,我用我的解决方案更新了问题。
-
如果您有一个可行的解决方案但想要一些改进(性能、代码风格、架构等),那么最好在Code Review 上提问。
标签: c# algorithm linq grouping