如何使用LINQ检索包含列表中列表的多个属性的条目?

时间:2019-04-04 08:40:04

标签: c# linq

我有一个IJapaneseDictionaryEntry对象的列表,如下所述。在其中的IKanji对象包含Priorites对象。

我有一件非常困难的事情想做,并且希望得到任何建议。我想做的是从列表{{中检索具有Priority为“ Frequency1”的条目具有Priority为“ Frequency2”或Priority为“ Frequency2”的条目。 1}}。

entries

每个对象都包含public interface IJapaneseDictionaryEntry { int Sequence { get; } IEnumerable<IKanji> Kanjis { get; } IEnumerable<IReading> Readings { get; } IEnumerable<ISense> Senses { get; } } 个对象的列表

IKanji

以下是列表:

public interface IKanji
{
    string Text { get; }
    IEnumerable<KanjiInformation> Informations { get; }
    IEnumerable<Priority> Priorities { get; }
}

以下是我认为可能有助于解释其内容的一种观点:

enter image description here

我希望这里的信息足够,因为似乎很难解释我需要检索的内容。

2 个答案:

答案 0 :(得分:2)

var result = entries.Where(e => e.Kanjis.Any(k => k.Priorities.Contains(Priority.Frequency1) ||
k.Priorities.Contains(Priority.Frequency2) ||
k.Priorities.Contains(Priority.Frequency3)
)).ToList();

考虑到您的两个问题,我会做这样的事情:

[Flags]
public enum Priority
{
     Frequency1 = 1,
     Frequency2 = 2,
     Frequency3 = 4,
     Frequency4 = 8
}

public interface IKanji
{
    string Text { get; }
    IEnumerable<KanjiInformation> Informations { get; }
    Priority Priorities { get; }
}

在上面的示例中,将每个优先级视为一个整数中的bit,您可以使用按位或(|)来添加优先级:

优先级= Priority.Frequency1 | Priority.Frequency2 //表示同时具有两个优先级

要检查其是否具有特定优先级,请按位和(&):

if((Priorities & Priority.Frequency1) == Priority.Frequency1
{
     // it contains Priority.Frequency1
}

然后您正在寻找的答案将是:

Priority p = Priority.Frequency1 | Priority.Frequency2 | Priority.Frequency3

var result = entries.Where(e => e.Kanjis.Any(k => k.Priorities & p == p)))
.ToList();

答案 1 :(得分:2)

这可能是一种解决方案:

var filteredEntries = entries.Where( // Only entries
    e => e.Kanjis.Any( // which have one or more kanjis with..
        a => a.Priorities.Any( // which have one or more priorities                    
            p => p.Value == "Frequency1" // which have a value of "Frequency1"
            )));

我将您的interfaces更改为classes,使其与某些示例数据一起运行:

public class IJapaneseDictionaryEntry
{
    public int Sequence { get; set; }
    public IEnumerable<IKanji> Kanjis { get; set; }
}
public class IKanji
{
    public string Text { get; set; }
    public IEnumerable<Priority> Priorities { get; set; }
}

public class Priority
{
    public string Value { get; set; }
}

public static void Main(string[] args)
{
    // Initialize 3 objects. One has Priority we're searching
    List<IJapaneseDictionaryEntry> entries = new List<IJapaneseDictionaryEntry>()
    {
        new IJapaneseDictionaryEntry(){ Sequence = 1, Kanjis = new List<IKanji>() { new IKanji() { Priorities = new List<Priority>() { new Priority() { Value = "Frequency1" } } } } },
        new IJapaneseDictionaryEntry(){ Sequence = 2, Kanjis = new List<IKanji>() { new IKanji() { Priorities = new List<Priority>() { new Priority() { Value = "Frequency2" } } } } },
        new IJapaneseDictionaryEntry(){ Sequence = 3, Kanjis = new List<IKanji>() { new IKanji() { Priorities = new List<Priority>() { new Priority() { } } } } },
    };

    // Here's the magic:
    var filteredEntries = entries.Where( // Only entries
        e => e.Kanjis.Any( // which have one or more kanjis with..
            a => a.Priorities.Any( // which have one or more priorities                    
                p => p.Value == "Frequency1" // which have a value of "Frequency1"
                )));

    // Let's check the output
    foreach (var e in filteredEntries)
    {
        Console.WriteLine(e.Sequence);
    }
}