提问人:Nishanth 提问时间:8/22/2023 更新时间:8/22/2023 访问量:49
如何使用另一个列表根据条件筛选对象列表
How to Filter a List of Objects based on a Condition using another list
问:
我正在尝试解决想要根据另一个值列表过滤值的问题
清单 1:
[
{"Number":"324234","PhoneType":"Cell"},
{"Number":"645645","PhoneType":"Work"},
{"Number":"3453453","PhoneType":"phone"},
{"Number":"342","PhoneType":"fax"}
]
清单 2:
["Work","Cell","phone","Fax"]
条件: 我想按给定的顺序过滤基于列表 1 的列表 2 值。
如果列表 2 在所有条件下都不会相同,有时它只会有单元格和工作,有时它只会有工作,有时它会有工作、手机、电话和传真我们在过滤时不需要考虑电话类型传真,并且列表 2 中的顺序每次都会不同
例:列表 2 将工作作为第一个值,如果我们在列表 1 中有电话类型工作,那么我们只需要从列表 1 中获取该记录,如果列表 1 没有工作,则必须查找电话类型单元格,因为它是列表 2 中的第二个值
我想使用 Lamda 函数或每个函数来解决这个问题
我的尝试1:
var results = List1.Where((item, index) => list2[index] == "work");
这里的电话类型应该来自列表 2
我的尝试 2
var primaryPhone = list1?.FirstOrDefault(p => !p.PhoneType.Equals("Fax") && !p.MediaType.Equals("Fax"));
默认情况下,上面的行仅返回列表 1 中的第一条记录
有人可以帮助我根据给定顺序的列表 1 值从列表 2 中找到记录吗
答:
1赞
Oliver
8/22/2023
#1
首先,我们需要一些 C# 类,其中包含您想要的信息:
public record PhoneEntry(string Number, PhoneType PhoneType);
public enum PhoneType
{
Cell,
Work,
Phone,
Fax
}
接下来,我们需要一个比较器,它将所需顺序的列表作为输入:
public class PhoneTypeComparer : IComparer<PhoneType>
{
private readonly IReadOnlyDictionary<PhoneType, int> ordering;
public PhoneTypeComparer(IReadOnlyCollection<PhoneType> ordering)
{
this.ordering = ordering
.Select((x, i) => (x, i))
.ToDictionary(x => x.x, x => x.i);
}
public int Compare(PhoneType x, PhoneType y)
{
if (x == y)
return 0;
if (!ordering.TryGetValue(x, out int xWeight))
xWeight = 1_000_000;
if (!ordering.TryGetValue(y, out int yWeight))
yWeight = 1_000_000;
return xWeight - yWeight;
}
}
然后,让我们将给定的数据反序列化为新类:
var jsonEntries = """
[
{"Number":"324234","PhoneType":"Cell"},
{"Number":"645645","PhoneType":"Work"},
{"Number":"3453453","PhoneType":"phone"},
{"Number":"342","PhoneType":"fax"}
]
""";
var jsonFilter = """
["Cell","Work","phone","Fax"]
""";
var options = new JsonSerializerOptions
{
Converters = { new JsonStringEnumConverter() }
};
var entries = JsonSerializer.Deserialize<PhoneEntry[]>(jsonEntries, options)
?? throw new ArgumentNullException(nameof(jsonEntries));
var filter = JsonSerializer.Deserialize<PhoneType[]>(jsonFilter, options)
?? throw new ArgumentNullException(nameof(jsonFilter));
然后,我们需要从过滤器创建一个比较器,并将其应用于给定的列表以对其进行排序:
var comparer = new PhoneTypeComparer(filter);
var ordered = entries
.OrderBy(entry => entry.PhoneType, comparer)
.ToList();
最后打印出新的订单:
foreach (var entry in ordered)
{
Console.WriteLine($"{entry.PhoneType}: {entry.Number}");
}
如果您只需要筛选定义的值并选择第一个值,则必须将它们排序并选择第一个:
var desired = entries
.Join(filter, entry => entry.PhoneType, type => type, (entry, type) => entry)
.OrderBy(entry => entry.PhoneType, comparer)
.FirstOrDefault();
0赞
Orion
8/22/2023
#2
请尝试以下筛选器。
var listToFilter = new List<Phone>()
{
new() { Number = "324234", PhoneType = "Cell" },
new() { Number = "645645", PhoneType = "Work" },
new() { Number = "3453453", PhoneType = "Phone" },
new() { Number = "342", PhoneType = "Fax" }
};
var filterList = new[] { "Work", "Cell", "Phone", "Fax" };
Phone matchingPhone = null;
foreach (var filter in filterList)
{
matchingPhone = listToFilter.FirstOrDefault(p => p.PhoneType == filter);
if (matchingPhone is not null)
break;
};
示例如下: https://dotnetfiddle.net/d9pP3k
作为功能:
private static Phone GetMatchingPhone(IEnumerable<Phone> phones, IEnumerable<string> filters)
{
foreach (var filter in filters)
{
var matchingPhone = phones.FirstOrDefault(p => p.PhoneType == filter);
if (matchingPhone is not null)
return matchingPhone;
};
return null;
}
评论