LINQ join:结构列表的灵活性

时间:2017-07-29 14:22:59

标签: c# list linq variables struct

如果问题是愚蠢的话,我会道歉,我想知道一些简化我的代码的事情:

我有几个清单:

public struct structure
{
     public string item1;
     public string item2;
     public string item3;
     public string item4;
}
public List <structure> listOfStruct=new List <structure>();
public List <string> lista;
public List <string> listb;

使用下面的代码我使用LINQ连接来查找两个列表中的匹配项:

                    query = from x in listOfStruct
                        join y2 in lista on x.item1 equals y2
                        select new
                        {
                            x.action
                        };

                        foreach (var item in query)
                        { 
                            Answer = item.answer;
                        }

然后使用变量'Answer'进行进一步处理。

问题是我的代码中的其他地方我需要将另一个列表与listOfStruct匹配,但是与结构的另一个项匹配:

                    query = from x in listOfStruct
                        join y2 in listB on x.item2 equals y2
                        select new
                        {
                            x.action
                        };


                        foreach (var item in query)
                        { 
                            Answer = item.answer;
                        }

我想写一个像这样的函数

public string matchList(string actionListItem, string [] second_list){
                       query = from x in listOfStruct
                            join y2 in second_list on x.actionListItem equals y2
                            select new
                            {
                                x.action
                            };

                            foreach (var item in query)
                            { 
                                Answer = item.answer;
                            }
                            return Answer;
}

并且如果我的程序中的任何地方都使用下面的内容进行调用,那就是要灵活一点并且不要反复写同一段代码:

var action= matchList(string itemInlistOfStruct,string []secondList)

其中“itemInListOfStruct”可以是item1,item2 ...或item4和“seconList”lista或listb。

这可能吗?

2 个答案:

答案 0 :(得分:0)

您必须为结构定义与Strings的比较。使用以下过程执行此操作

public struct structure
{
     public string item1;
     public string item2;
     public string item3;
     public string item4;

     public override bool Equals(string obj) 
     {

      return obj==item1;//your code for check Equals
     }

}

答案 1 :(得分:0)

无论您使用listOfStruct的匹配元素做什么(在您的问题中确实非常不清楚),过滤掉这些匹配与连续处理它们无关。所以我建议将匹配和进一步处理分成两个更简单的步骤。

在这种情况下,我更喜欢使用类而不是结构,因此我将结构structure重命名为类Thing,同时更改Item2的类型用于演示目的:

public sealed class Thing
{
    public string Item1 { get; set; }
    public int Item2 { get; set; }
    // ...
}

现在根据需要制作一些扩展方法:

public static class MyExtensions
{
    public static IEnumerable<TSource> MatchBy<TSource, TItem>(this IEnumerable<TSource> source, Func<TSource, TItem> keySelector, IEnumerable<TItem> keys)
    {
        var keySet = keys as ISet<TItem> ?? new HashSet<TItem>(keys);
        return source.Where(x => keySet.Contains(keySelector(x)));
        // or equivalently, if you prefer
        // return from x in source where keySet.Contains(keySelector(x)) select x;
    }

    public static string FurtherProcessing(this IEnumerable<Thing> things) => $"Number of things: {things.Count()}.";
}

并像这样使用它们:

    var things = new List<Thing>
    {
        new Thing { Item1 = "Foo", Item2 = 0 },
        new Thing { Item1 = "Bar", Item2 = 1 },
        new Thing { Item1 = "Bla", Item2 = 2 },
    };
    var answerByItem1 = things.MatchBy(thing => thing.Item1, new[] { "Foo", "Bar" }).FurtherProcessing();
    var answerByItem2 = things.MatchBy(thing => thing.Item2, new[] { 1 }).FurtherProcessing();

如果您的所有ItemXXX都是字符串,并且您确实需要按名称识别它们,则可以添加另一个MatchBy重载:

public static IEnumerable<Thing> MatchBy(this IEnumerable<Thing> source, string keyName, IEnumerable<string> keys)
{
    switch (keyName)
    {
        case nameof(Thing.Item1): return source.MatchBy(x => x.Item1, keys);
        // case ...
        default: throw new ArgumentOutOfRangeException(nameof(keyName));
    }
}