C# 如何使用linq查找存在特定字符串的列表?
我有一个包含两个列表的类C# 如何使用linq查找存在特定字符串的列表?,c#,linq,C#,Linq,我有一个包含两个列表的类 public class SchemaView { public int Version { get; set; } public IEnumerable<EntityView> Entities { get; set; } public IEnumerable<RelationView> Relations { get; set; } } 可能添加一个或条件的地方? 所以它也会在
public class SchemaView
{
public int Version { get; set; }
public IEnumerable<EntityView> Entities { get; set; }
public IEnumerable<RelationView> Relations { get; set; }
}
可能添加一个或条件的地方?
所以它也会在关系中搜索一个名为某物的内部名称
上面的一个在关系列表中搜索失败,但是这个搜索不能被包装在同一个linq中,或者我需要为这个单独创建一个linq,
或者是有条件的
这样做能更有效吗
.Entities.Any(x => x.InternalName == entityName) ? .Entities
.FirstOrDefault(x => x.InternalName == entityName).Attributes .Select(x => x.InternalName) : .Relations.FirstOrDefault(x => x.InternalName == entityName).Attributes.Select(x => x.InternalName);
因此,您有一系列的
SchemaViews
,每个SchemaView都有零个或多个实体
和零个或多个关系
你写道:
我正在寻找linq查询,它可以为我找到属性==“something”的实体或关系
是否只有一个属性==某物的实体/关系?或者您的SchemaViews可以有多个实体和关系,这些实体和关系的属性值为该值。您是在实体和关系中查找任何属性,还是在查找某些特定属性,例如propertyInternalName
?是否只有实体具有此属性,或者关系是否也具有内部名称
?还是要将关系用于其他属性
一旦你找到了这样一个实体或关系,你是想要完整的实体/关系,还是想要选择它的一些属性
这么少的课文里有这么多的问题。考虑编辑你的问题,写一个非模糊的要求。< /P>
我想你的意思是:
要求
给定一系列SchemaView,其中每个SchemaView都有零个或多个实体和零个或多个关系,每个实体都有一个TKey类型的PropertyA属性,每个关系都有一个TKey类型相同的PropertyB属性。同样给定TKey类型的对象value
,给我所有实体和所有SchemaView的关系的连接,这些实体和关系的PropertyA或PropertyB等于value
当然,问题是关系不是实体,所以不能将它们放在一个序列中,否则它将是一个对象序列,这可能不是您想要的。显然,您还需要一个选择实体属性的elementSelectorA
,以及一个选择关系属性的elementSelectorB
,两个选择的元素应该是相同的类型
当然,您可以使用Concat
,来连接实体和关系:
IEnumerable<SchemaView> schemaViews = ...
IEnumerable<TResult> selectedEntities = schemaViews.SelectMany(...).Where(...)
IEnumerable<TResult> selectedRelations = schemaView.SeelctMany(...).Where(...)
IEnumerable<TResult> result = selectedEntities.Concat(selectedRelations);
用法:
string internalName = ...
IEnumerable<SchemaView> schemaViews = ...
IEnumerable<MyResultClass> results = schemaViews.SelectDoubleMany(internalName);
一旦找到一个实体或关系,就会停止枚举
为了简单起见,我没有使用任何LINQ。我认为这是最有效的方法(除了低级的GetEnumerator/MoveNext)。只枚举最终结果中实际使用的元素
通解
如果希望将其作为泛型方法,则需要大量参数
- 输入`IEnumerable源
- 每个TSource都有两个类型的属性:
IEnumerable
和'IEnumerable'。您需要两个CollectionSelector,就像SelectMany一样
- 每个TSub1都有一个类型为
TKey
的属性;每个TSub2都有一个相同类型的属性TKey
,在Join
- 您只需要TKey值等于某个输入值的项
- 您需要一个参数来将每个剩余的TSub1转换为TResult
- 您需要一个参数来将每个剩余的TSub2转换为TResult
- 最后:对于完全通用:您需要一个
IEqualityComparer
我的天,这是一个相当长的参数列表。但是,您可以使用它来选择具有两个子集合的DoubleMany每个集合
这些参数类似于SelectMany与Where的组合,只是所有参数都是双重的。首先,一个没有EqualityComparer的方法,与许多LINQ方法一样,它只调用另一个重载
public static IEnumerable<TResult> SelectDoubleMany<TSource, Tsub1, Tsub2, TKey, TResult>(
IEnumerable<TSource> source,
// Two subcollection selectors, like in SelectMany:
Func<TSource, TSub1> collectionSelector1,
Func<STrouce, TSub2> CollectionSelector2,
// the two KeySelectors, like in Join:
Func<Tsub1, TKey> key1Selector,
Func<Tsub2, TKey> key2Selector,
// the "InternalName" that you want
TKey value,
// Two resultSelectors that convert Tsub1 and Tsub2 into TResult
Func<Tsub1, TResult> resultSelector1,
Func<Tsub1, TResult> resultSelector2)
{
// call the overload with an equalitycomparer:
return source.SelectDoubleMany(
collectionSelector1,
collectionSelector2,
keySelector1,
keySelector2,
value,
resultSelector1,
resultSelector2,
null); // <== null equalityComparer
}
公共静态IEnumerable SelectDoubleMany(
IEnumerable来源,
//两个子集合选择器,如SelectMany中的:
Func CollectionSelector 1,
Func CollectionSelector 2,
//两个关键点选择器,如Join:
Func Key1选择器,
Func Key2选择器,
//您想要的“内部名称”
TKey值,
//将Tsub1和Tsub2转换为TResult的两个结果选择器
Func结果选择器1,
Func结果选择器2)
{
//使用equalitycomparer调用重载:
返回source.SelectDoubleMany(
收藏选择1,
收藏选择2,
按键选择器1,
按键选择器2,
价值
结果选择器1,
结果选择器2,
null);//我不确定我是否理解该问题。例如,InternalName
属于哪个实体。请编辑该问题并提供一个。因此您有一个IEnumerable,并希望从该集合中提取所有具有实体的条目。PropertyA==“something”或Relations.PropertyB==“something”.对吗?@Steve yes Steven投票决定重新开始。很抱歉,但在最初发布问题时,尽最大努力解释你的问题是非常重要的。正如你所看到的,如果有人不理解你的问题,那么很快就会结束。对你来说,11分钟,今天在SOLinq上不是忙碌的一天,这并不是什么神奇的事情。查询两次相同的问题t会对性能造成惩罚。最好使用普通循环,然后只检查一次每个SchemaView
string internalName = ...
IEnumerable<SchemaView> schemaViews = ...
IEnumerable<MyResultClass> results = schemaViews.SelectDoubleMany(internalName);
var results = schemaVies.Where(schamaView => schemaView.Id == 42)
.SelectDoubleMany(internalName)
.GroupBy(myResult => myResult.Id)
.FirstOrDefault();
public static IEnumerable<TResult> SelectDoubleMany<TSource, Tsub1, Tsub2, TKey, TResult>(
IEnumerable<TSource> source,
// Two subcollection selectors, like in SelectMany:
Func<TSource, TSub1> collectionSelector1,
Func<STrouce, TSub2> CollectionSelector2,
// the two KeySelectors, like in Join:
Func<Tsub1, TKey> key1Selector,
Func<Tsub2, TKey> key2Selector,
// the "InternalName" that you want
TKey value,
// Two resultSelectors that convert Tsub1 and Tsub2 into TResult
Func<Tsub1, TResult> resultSelector1,
Func<Tsub1, TResult> resultSelector2)
{
// call the overload with an equalitycomparer:
return source.SelectDoubleMany(
collectionSelector1,
collectionSelector2,
keySelector1,
keySelector2,
value,
resultSelector1,
resultSelector2,
null); // <== null equalityComparer
}
public static IEnumerable<TResult> SelectDoubleMany<TSource, Tsub1, Tsub2, TKey, TResult>(
IEnumerable<TSource> source,
// Two subcollection selectors, like in SelectMany:
Func<TSource, IEnumerable<Tsub1>> collectionSelector1,
Func<TSource, IEnumerable<Tsub2>> CollectionSelector2,
// the two KeySelectors, like in Join:
Func<Tsub1, TKey> key1Selector,
Func<Tsub2, TKey> key2Selector,
// the "InternalName" that you want
TKey value,
// Two resultSelectors that convert Tsub1 and Tsub2 into TResult
Func<Tsub1, TResult> resultSelector1,
Func<Tsub1, TResult> resultSelector2,
IEqualityComparer<TKey> comparer)
{
// If the equality comparer is null, use the default comparer:
if (comparer == null)
{
comparer = EqualityComparer<TKey>.Default;
}
// code is similar to the code above, only generic:
foreach (TSource sourceElement in source)
{
IEnumerable<Tsub1> subCollection1 = collectionSelector1(sourceElement);
foreach(Tsub1 subCollectionElement in subCollection1)
{
TKey key = keySelector1(subCollectionElement);
if (comparer.Equals(key, value))
{
TResult result = result1Selector(subCollectionElement);
yield return result;
}
}
IEnumerable<Tsub2> subCollection2 = collectionSelector2(sourceElement);
foreach(Tsub2 subCollectionElement in subCollection2)
{
TKey key = keySelector1(subCollectionElement);
if (comparer.Equals(key, value))
{
TResult result = result1Selector(subCollectionElement);
yield return result;
}
}
}
}