我觉得我想要的东西应该存在,但我不知道它叫什么。所有搜索" regex for objects"只返回有关正常RegEx的教程和问题。搜索"模式匹配"返回有关C#7新模式匹配功能的新闻,这不是我想要完成的事情。
为了说明我之后的内容,假设你有以下课程:
public class Car
{
public string Color { get; set; }
public int MilesDriven { get; set; }
public bool IsAllWheelDrive { get; set; }
}
然后假设您有一个具有随机和不同属性的Car对象列表。我希望能够在列表中搜索类似RegEx的模式,并获得模式发生的每个实例的开始和结束索引。
示例模式将是:
查找所有车轮在2辆蓝色轿车之间发生并且第一辆蓝色轿车上行驶超过1000英里的情况。
查找红色汽车紧随其后至少有2辆绿色汽车的所有情况,最后是一辆行驶不到100英里的汽车。
这是一个人为的问题,但我想知道是否存在这样的问题,最好是现有的C#库。
道歉,如果"模式匹配"不是这个问题的适用标签,但正如我所说的那样,我真的不知道如果有的话,可以称之为。
答案 0 :(得分:0)
您正在寻找的是过滤器概念。 C#确实为列表提供了这样一个概念的应用程序,但是如果你不只是试图过滤对象的属性,它会变得复杂。 Microsoft通过LINQ使用this post或this post作为示例,使C#的过滤功能具有通用性:
基本上语法是:
var newlist = list.linqquery1.linquery2...linqueryN.Where(s.x condition);
当然,如果它足够简单,你可以做到以下几点:
var newlist = list.Where(s.x condition);
但是您的问题还要求根据列表中的后续项目进行选择。这要复杂得多,因为除非将数据附加到列表中的元素,否则您将无法访问这些元素。例如,如果您的listelem
实际上是一个doubly linked list节点,您可以在病房列表中向前看,仅基于前向节点参考并运行这样的条件(检查两个绿色)汽车跟随):
var green2follows = carlist.Where(s.next.type == greencar && s.next.next.type == greencar);
但是,如果你自己用迭代来表达这种情况,你可以对使用双链表的情况进行总结。不幸的是,因为LINQ主要用于基于枚举的查询,所以你必须找到解决方法来使用微软内置的微软进行过滤(虽然这不是微软独有的,通常你不在查询中包含局部性)This post涵盖那个结论。
要迭代地执行此操作,您将创建一个for循环并针对i + 1和i + 2值的汽车进行测试。请小心,因为这会使先前的值变得混乱(i-n)迭代器可能对此有好处以避免错误,尽管我不确定c#是否像其他语言一样支持迭代器算法以允许您前后移动。您可能被迫制作自定义迭代器以通常定义此类过滤器。
编辑:你可以避免创建一个自定义迭代器,只创建一个迭代器返回的自定义对象,它通过迭代器块支持向前和向后查看(比如answer suggest in this post)你可能会做的是这样的事情:
HandleObject<T>...
...
public bool backwardsWhere(condition)...
public bool forwardsWhere(condition)...
public bool backwardsNWhere(n, condition);
public bool forwardsNWhere(condition);
//other forwards filter functions for convienience
// get back the element that we wraped
public T get();
static IEnumerable<T> iteratorBlock(List<T> list)
{
foreach (int i = 0; i < list.Length; i++)
{
// yield means a new HandleObject is only created upon access, and
// need not be stored otherwise
yield return HandleObject<T>(i, list);
}
}
不使用你的列表和LINQing,而是使用这个迭代器而不是模板列表,这样你就不必在C#中处理讨厌的迭代器语义来创建你自己的whilist仍然能够实现所有的功能你需要查看清单。
var customIterableFromBlock = iteratorBlock<Car>(carlist);
var selectedCars = from handleCar in customIterableFromBlock
where ... //handleCar.backwardsWhere(...)&& handleCar.forwardsWhere(...)
//handleCar.get().x == condition etc
select Car
{
//get Car from handleCar.get()
};
您在i
构造函数中包含HandleObject
和列表本身的原因是允许根据传入的位置i
向前和向后搜索列表。