如何按Package的SearchCount排序规则对关联Tiger列表排序
问题需求
从两个JSON文件分别获取以下数据:
- Package列表:已按
SearchCount(ulong类型)降序排序,每个Package包含唯一GUID和对应的SearchCount - Tiger列表:每个Tiger包含Pizza列表,Pizza的
LinkedLeaves属性是GUID列表,其中大部分GUID存在于Package列表中
需要实现:
- 筛选出所有包含至少一个Pizza(其LinkedLeaves包含Package中GUID)的Tiger,取前n个
- 让筛选后的Tiger列表按照关联Package的SearchCount降序排序,和Package列表的排序规则对齐
- 处理Pizza.LinkedLeaves包含多个GUID(部分不属于高SearchCount Package)的场景
现有代码
Pizza类
public sealed class Pizza { public List<Guid> LinkedLeaves { get; internal set; } public Pizza(List<Guid> linkedLeaves) { this.LinkedLeaves = linkedLeaves; } }
Tiger类
public sealed class Tiger { public Guid Id { get; internal set; } public string Name { get; internal set; } = string.Empty; public List<Pizza> PizzaList { get; internal set; } public Tiger(Guid id, string name, List<Pizza> pizzaList) { this.Id = id; this.Name = name; this.PizzaList = pizzaList; } public Tiger() { } }
Package类
public sealed class Package { public Guid GuidId { get; private set; } public ulong SearchCount { get; internal set; } public Package(ulong searchCount, Guid guidId) { this.SearchCount = searchCount; this.GuidId = guidId; } }
业务逻辑类C
public class C { private Guid Guid1 = Guid.Parse("21e8c8bc-cf89-4efd-896b-f30cae27a960"); private Guid Guid2 = Guid.Parse("8bf745b7-9505-4234-90f3-5b41446b8c08"); private Guid Guid3 = Guid.Parse("fb208508-1c19-4bc3-a2cd-ad9da6d576da"); private Guid Guid4 = Guid.NewGuid(); private Guid Guid5 = Guid.NewGuid(); private void Run() { /* 5个Package,对应不同GUID,已按SearchCount降序排序 */ List<Package> packages = GetMostPopularPackages(); /* 获取包含Package中GUID的Tiger,取前3个,但当前排序不符合Package的规则 */ List<Tiger> tigers = GetTigersWithContainedPackages(packages.Select(p => p.GuidId).ToList(), 3); // 需要在这里实现排序 System.Diagnostics.Debug.WriteLine(packages[0].GuidId.ToString() + " " + tigers[0].PizzaList[0].LinkedLeaves[0].ToString()); System.Diagnostics.Debug.WriteLine(packages[1].GuidId.ToString() + " " + tigers[1].PizzaList[0].LinkedLeaves[0].ToString()); } private List<Tiger> GetTigersWithContainedPackages(List<Guid> guids, int count) { List<Tiger> readTigers = GetRandomTigers(3); List<Tiger> matchingTigers = readTigers .Select(t => new Tiger { Id = t.Id, Name = t.Name, PizzaList = t.PizzaList .Where(p => p.LinkedLeaves != null && p.LinkedLeaves.Any(id => guids.Contains(id))) .ToList() }) .Where(t => t.PizzaList.Count > 0) .Take(count) .ToList(); return matchingTigers; } private List<Tiger> GetRandomTigers(int count) { List<Tiger> tigers = new List<Tiger>(); List<Pizza> pizzas1 = new List<Pizza>(); pizzas1.Add(new Pizza(new List<Guid>() { Guid1 })); tigers.Add(new Tiger(Guid.NewGuid(), "Ahmed", pizzas1)); List<Pizza> pizzas2 = new List<Pizza>(); pizzas2.Add(new Pizza(new List<Guid>() { Guid3 })); tigers.Add(new Tiger(Guid.NewGuid(), "Benjamin", pizzas2)); List<Pizza> pizzas3 = new List<Pizza>(); pizzas3.Add(new Pizza(new List<Guid>() { Guid2 })); tigers.Add(new Tiger(Guid.NewGuid(), "Charlie", pizzas3)); return tigers; } private List<Package> GetMostPopularPackages() { List<Package> packages = new List<Package>(); packages.Add(new Package(0ul, Guid4)); packages.Add(new Package(4ul, Guid2)); packages.Add(new Package(5ul, Guid1)); packages.Add(new Package(2ul, Guid3)); packages.Add(new Package(1ul, Guid5)); return packages.OrderByDescending(p => p.SearchCount).ToList(); } }
解决方案
要实现Tiger列表按关联Package的SearchCount降序排序,核心步骤如下:
- 先将Package的GUID与对应的SearchCount存入字典,避免重复查找,提升效率
- 对每个Tiger,计算其所有关联Package中的最高SearchCount(处理一个Pizza包含多个GUID的场景)
- 按照该最高SearchCount对Tiger列表进行降序排序
修改Run方法中的排序部分,代码如下:
private void Run() { List<Package> packages = GetMostPopularPackages(); List<Tiger> tigers = GetTigersWithContainedPackages(packages.Select(p => p.GuidId).ToList(), 3); // 1. 构建GUID到SearchCount的映射字典 var guidToSearchCount = packages.ToDictionary(p => p.GuidId, p => p.SearchCount); // 2. 排序Tiger列表:按关联的最高SearchCount降序,若SearchCount相同则保持原顺序(可选) tigers = tigers.OrderByDescending(t => // 获取当前Tiger所有有效GUID对应的最高SearchCount t.PizzaList .SelectMany(p => p.LinkedLeaves) .Where(guid => guidToSearchCount.ContainsKey(guid)) .Select(guid => guidToSearchCount[guid]) .DefaultIfEmpty(0) // 无匹配GUID时默认0,确保不会出错 .Max() ).ToList(); System.Diagnostics.Debug.WriteLine(packages[0].GuidId.ToString() + " " + tigers[0].PizzaList[0].LinkedLeaves[0].ToString()); System.Diagnostics.Debug.WriteLine(packages[1].GuidId.ToString() + " " + tigers[1].PizzaList[0].LinkedLeaves[0].ToString()); }
说明
- 字典
guidToSearchCount实现O(1)时间复杂度的GUID查找,比每次遍历Package列表更高效 - 使用
SelectMany扁平化Tiger下所有Pizza的LinkedLeaves GUID,再筛选出存在于Package中的GUID - 取这些GUID对应的SearchCount的最大值作为Tiger的排序依据,确保即使一个Pizza包含多个GUID,也按最高的SearchCount排序
DefaultIfEmpty(0)处理极端情况:Tiger的Pizza中没有匹配的GUID(虽然筛选逻辑已经过滤,但做保底处理更健壮)
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

