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可以有多个实体和关系,这些实体和关系的属性值为该值。您是在实体和关系中查找任何属性,还是在查找某些特定属性,例如property
InternalName
?是否只有实体具有此属性,或者关系是否也具有
内部名称
?还是要将关系用于其他属性

一旦你找到了这样一个实体或关系,你是想要完整的实体/关系,还是想要选择它的一些属性

这么少的课文里有这么多的问题。考虑编辑你的问题,写一个非模糊的要求。< /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;
             }
         }
     }
}