C#LINQ在多个列表之间连接

时间:2017-07-25 19:42:30

标签: c# linq

我在C#中有一个LINQ Joining语句,我试图通过两个字符串列表来查找结构列表:

public struct ll
{
    public int index;
    public string one;
    public string two;
} 
public List <ll> list1;  //{"0,a, ", "1,," , "2,a,dog" , "3,,horse"}

public List <string> list2;    //{"a","b"}
public List <string> list3;    //{"cat","mouse","dog"}

这个想法是在list1中并不是所有的结构都包含一个值,所以在索引0上只有list1.one的值是&#34; a&#34;,list1.two是空的。在索引1上,list1.one和list1.two都是空的。在索引2上,list1.one和list.two都有值。在索引3上只有list.two有一个值。

下面我试图加入这三个列表

        var query = from x in list1
                    join y1 in list2 on x.one equals y1
                    join y2 in list3 on x.two equals y2
                    select x.index; 

使用此语句,只有list1.one匹配list2中的项目并且list1.two匹配list2中的项目时才会进行连接。 但是我想看到的是,如果只填充了list1.one,但list1.two为空,则join只会将list2中的项目与list1.one匹配,但会加入list3中的所有项目,因此空的list1.two不在帐户中。

编辑:

让我重新解释一下这个问题。我的目标是该程序读取用户输入的句子,将不定式,名词,文章和副词存储在单独的列表中,并尝试根据所有列表的连接为用户找到最佳答案或答复。

所以list1看起来应该是

    public struct ll
    {
       int index;
       string infinitive;
       string noun;
       string article;
       string adverb;
       string answer;

    }
public List <ll> list1;

以下数据:

enter image description here

例如,当用户输入句子时,你能找到什么&#39;连接脚本应该返回两个可能的答案:

&#34;我可以找到这些信息&#34;和#34;你希望我找到什么&#34;

关于句子&#34;你能在这里找到什么&#34;

它只会返回: &#34;我可以找到这些信息&#34;

但当用户问:&#34;你对这个霍比特人有什么了解&#34;它将不会返回任何组合&#34;知道&#34;和&#34;这个&#34;是不知道的,在哪里&#34;你对霍比特人有什么了解&#34;将返回&#34;我知道&#34;

希望这更清楚知道

1 个答案:

答案 0 :(得分:0)

很难确切地说出你想要什么,特别是如何定义index,但我猜是这样的。您希望l1成为每个域的搜索字词的某种输入列表,并且您希望l2l3等成为某种搜索域。

JOIN不是解决这个问题的正确方法。您只是希望通过输入进行线性搜索,以进行域匹配。你可以很好地抽象出来,而不是让每个域都是它自己的列表,只需将它列为列表列表,然后按顺序搜索。具体如下:

var lists = new[]
                {
                    new[] { "a", null },
                    new string[] { null, null },
                    new[] { "a", "dog" },
                    new[] { null, "horse" }
                };
var domains = new[] { new[] { "a", "b" }, new[] { "cat", "mouse", "dog" } };

var matches = lists.Where(list => list.Where((s, i) => s == null || domains[i].Contains(s)).Count() == list.Length);

foreach (var list in matches)
{
    Console.WriteLine(string.Join(",", list));
}

输出:

"a",null
null,null
"a","dog"

当然,您可以编写一个函数来确定index中每个列表的相应matches值,如果这是您最终需要的。我建议你重新定义你的index是一个有点标志,而不是你描述的临时方式;那么你可以这样做:

static int GetIndex<T>(IEnumerable<T> list)
{
    return list.Select((s, i) => s == null ? 0 : 1 << i).Sum();
}

或者,如果您想内联所有内容,那么它只是

var indices = lists.Where(list => list.Where((s, i) => s == null || domains[i].Contains(s)).Count() == list.Length)
                   .Select(list => list.Select((s, i) => s == null ? 0 : 1 << i).Sum())
                   .Distinct();

或者,如果您定义一个好的帮助程序索引 - 所有LINQ函数,那么它可能会更清楚:

public static bool All<T>(this IEnumerable<T> seq, Func<T, int, bool> pred)
{
    return seq.Select((x, i) => Tuple.Create(x, i)).All(t => pred(t.Item1, t.Item2));
}

...

IEnumerable<int> indices = lists
    .Where(list => list.All((s, i) => s == null || domains[i].Contains(s)))
    .Select(list => list.Select((s, i) => s == null ? 0 : 1 << i).Sum())
    .Distinct();