Filter list of objects, where nested collection matches an array












2















I have a list of objects (items) which I would like to filter basis the values of a nested collection (Features in object GenericItem). As basis for the filter I have an array of int (filter). My objective is to find all objects in items where the Features collection includes at least all values in the filter array.



Following many solutions provided to others on Stackoverflow I have written the below. The problem I have is that in my Linq query (and the many variations I have tried) I always end up getting all objects in items where all Features are included in filter. I understand that my lambda expression is "in the wrong order", however because I want to end up with a list of GenericItem I can't seem to figure out how to write my expression.



How should I write the Linq expression to get the expected result?



So in the below, when I filter for an array of [2, 3] my objective is to get result holding "Item A" and "Item B" (both have at least features 2 and 3). Instead I get the result of "Item B" and "Item C" as all of their Features are included in the filter array.



public class GenericItem {
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Feature> Features { get; set; }
}

public class Feature {
public int Id { get; set; }
}

static void Main (string args) {

var items = new List<GenericItem>();
items.Add(new GenericItem() {
Id = 1,
Name = "Item A",
Features = new Collection<Feature>() {
new Feature() {Id = 1},
new Feature() {Id = 2},
new Feature() {Id = 3}
}
});
items.Add(new GenericItem() {
Id = 2,
Name = "Item B",
Features = new Collection<Feature>() {
new Feature() {Id = 2},
new Feature() {Id = 3}
}
});
items.Add(new GenericItem() {
Id = 3,
Name = "Item C",
Features = new Collection<Feature>() {
new Feature() {Id = 3}
}
});

int filter = new int {2, 3};

var resultAll = items.Where(i => i.Features.All(f => filter.Contains(f.Id)));

foreach (GenericItem I in resultAll)
System.Console.WriteLine(I.Name);
}









share|improve this question





























    2















    I have a list of objects (items) which I would like to filter basis the values of a nested collection (Features in object GenericItem). As basis for the filter I have an array of int (filter). My objective is to find all objects in items where the Features collection includes at least all values in the filter array.



    Following many solutions provided to others on Stackoverflow I have written the below. The problem I have is that in my Linq query (and the many variations I have tried) I always end up getting all objects in items where all Features are included in filter. I understand that my lambda expression is "in the wrong order", however because I want to end up with a list of GenericItem I can't seem to figure out how to write my expression.



    How should I write the Linq expression to get the expected result?



    So in the below, when I filter for an array of [2, 3] my objective is to get result holding "Item A" and "Item B" (both have at least features 2 and 3). Instead I get the result of "Item B" and "Item C" as all of their Features are included in the filter array.



    public class GenericItem {
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Feature> Features { get; set; }
    }

    public class Feature {
    public int Id { get; set; }
    }

    static void Main (string args) {

    var items = new List<GenericItem>();
    items.Add(new GenericItem() {
    Id = 1,
    Name = "Item A",
    Features = new Collection<Feature>() {
    new Feature() {Id = 1},
    new Feature() {Id = 2},
    new Feature() {Id = 3}
    }
    });
    items.Add(new GenericItem() {
    Id = 2,
    Name = "Item B",
    Features = new Collection<Feature>() {
    new Feature() {Id = 2},
    new Feature() {Id = 3}
    }
    });
    items.Add(new GenericItem() {
    Id = 3,
    Name = "Item C",
    Features = new Collection<Feature>() {
    new Feature() {Id = 3}
    }
    });

    int filter = new int {2, 3};

    var resultAll = items.Where(i => i.Features.All(f => filter.Contains(f.Id)));

    foreach (GenericItem I in resultAll)
    System.Console.WriteLine(I.Name);
    }









    share|improve this question



























      2












      2








      2








      I have a list of objects (items) which I would like to filter basis the values of a nested collection (Features in object GenericItem). As basis for the filter I have an array of int (filter). My objective is to find all objects in items where the Features collection includes at least all values in the filter array.



      Following many solutions provided to others on Stackoverflow I have written the below. The problem I have is that in my Linq query (and the many variations I have tried) I always end up getting all objects in items where all Features are included in filter. I understand that my lambda expression is "in the wrong order", however because I want to end up with a list of GenericItem I can't seem to figure out how to write my expression.



      How should I write the Linq expression to get the expected result?



      So in the below, when I filter for an array of [2, 3] my objective is to get result holding "Item A" and "Item B" (both have at least features 2 and 3). Instead I get the result of "Item B" and "Item C" as all of their Features are included in the filter array.



      public class GenericItem {
      public int Id { get; set; }
      public string Name { get; set; }
      public ICollection<Feature> Features { get; set; }
      }

      public class Feature {
      public int Id { get; set; }
      }

      static void Main (string args) {

      var items = new List<GenericItem>();
      items.Add(new GenericItem() {
      Id = 1,
      Name = "Item A",
      Features = new Collection<Feature>() {
      new Feature() {Id = 1},
      new Feature() {Id = 2},
      new Feature() {Id = 3}
      }
      });
      items.Add(new GenericItem() {
      Id = 2,
      Name = "Item B",
      Features = new Collection<Feature>() {
      new Feature() {Id = 2},
      new Feature() {Id = 3}
      }
      });
      items.Add(new GenericItem() {
      Id = 3,
      Name = "Item C",
      Features = new Collection<Feature>() {
      new Feature() {Id = 3}
      }
      });

      int filter = new int {2, 3};

      var resultAll = items.Where(i => i.Features.All(f => filter.Contains(f.Id)));

      foreach (GenericItem I in resultAll)
      System.Console.WriteLine(I.Name);
      }









      share|improve this question
















      I have a list of objects (items) which I would like to filter basis the values of a nested collection (Features in object GenericItem). As basis for the filter I have an array of int (filter). My objective is to find all objects in items where the Features collection includes at least all values in the filter array.



      Following many solutions provided to others on Stackoverflow I have written the below. The problem I have is that in my Linq query (and the many variations I have tried) I always end up getting all objects in items where all Features are included in filter. I understand that my lambda expression is "in the wrong order", however because I want to end up with a list of GenericItem I can't seem to figure out how to write my expression.



      How should I write the Linq expression to get the expected result?



      So in the below, when I filter for an array of [2, 3] my objective is to get result holding "Item A" and "Item B" (both have at least features 2 and 3). Instead I get the result of "Item B" and "Item C" as all of their Features are included in the filter array.



      public class GenericItem {
      public int Id { get; set; }
      public string Name { get; set; }
      public ICollection<Feature> Features { get; set; }
      }

      public class Feature {
      public int Id { get; set; }
      }

      static void Main (string args) {

      var items = new List<GenericItem>();
      items.Add(new GenericItem() {
      Id = 1,
      Name = "Item A",
      Features = new Collection<Feature>() {
      new Feature() {Id = 1},
      new Feature() {Id = 2},
      new Feature() {Id = 3}
      }
      });
      items.Add(new GenericItem() {
      Id = 2,
      Name = "Item B",
      Features = new Collection<Feature>() {
      new Feature() {Id = 2},
      new Feature() {Id = 3}
      }
      });
      items.Add(new GenericItem() {
      Id = 3,
      Name = "Item C",
      Features = new Collection<Feature>() {
      new Feature() {Id = 3}
      }
      });

      int filter = new int {2, 3};

      var resultAll = items.Where(i => i.Features.All(f => filter.Contains(f.Id)));

      foreach (GenericItem I in resultAll)
      System.Console.WriteLine(I.Name);
      }






      c# arrays linq icollection






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 22 '18 at 18:27









      fnascimento

      9331117




      9331117










      asked Nov 22 '18 at 18:21









      Superman.LopezSuperman.Lopez

      576




      576
























          1 Answer
          1






          active

          oldest

          votes


















          1














          Apply All to the filter collection instead of the i.Features:



          var resultAll = items.Where(i => filter.All(x => i.Features.Any(f => x == f.Id)));





          share|improve this answer



















          • 1





            Thank you for your very quick solution!

            – Superman.Lopez
            Nov 22 '18 at 18:36











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436405%2ffilter-list-of-objects-where-nested-collection-matches-an-array%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          Apply All to the filter collection instead of the i.Features:



          var resultAll = items.Where(i => filter.All(x => i.Features.Any(f => x == f.Id)));





          share|improve this answer



















          • 1





            Thank you for your very quick solution!

            – Superman.Lopez
            Nov 22 '18 at 18:36
















          1














          Apply All to the filter collection instead of the i.Features:



          var resultAll = items.Where(i => filter.All(x => i.Features.Any(f => x == f.Id)));





          share|improve this answer



















          • 1





            Thank you for your very quick solution!

            – Superman.Lopez
            Nov 22 '18 at 18:36














          1












          1








          1







          Apply All to the filter collection instead of the i.Features:



          var resultAll = items.Where(i => filter.All(x => i.Features.Any(f => x == f.Id)));





          share|improve this answer













          Apply All to the filter collection instead of the i.Features:



          var resultAll = items.Where(i => filter.All(x => i.Features.Any(f => x == f.Id)));






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 '18 at 18:28









          AomineAomine

          42.3k74474




          42.3k74474








          • 1





            Thank you for your very quick solution!

            – Superman.Lopez
            Nov 22 '18 at 18:36














          • 1





            Thank you for your very quick solution!

            – Superman.Lopez
            Nov 22 '18 at 18:36








          1




          1





          Thank you for your very quick solution!

          – Superman.Lopez
          Nov 22 '18 at 18:36





          Thank you for your very quick solution!

          – Superman.Lopez
          Nov 22 '18 at 18:36




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53436405%2ffilter-list-of-objects-where-nested-collection-matches-an-array%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          Origin of the phrase “under your belt”?