2016-07-28 78 views
0

我被困在下面的问题C#LINQ: 我想加载一个目录,但我可以通过一个以上的参数可能是什么标准来找到我想要的清单。 现在我有以下结构:有两个列表

House{ 
    Name; 
    ID; 
    Alias; 
} 

我也有:

Person{ 
    Name; 
    Alias; 
} 

这意味着,1个可容纳多人,并与多个同名的人可以在多个房屋。 所以现在我想打电话给我的功能e.G. “GetHouses(字符串标准)”作为标准可以是:

  1. 房子
  2. 房子
  3. 房子
  4. 中的一个的名称的名称的一部分的ID的名称在房子里的人

现在我只是读了每一个房子,它的数据和我选择的标准之后。

重要提示:我不能改变的逻辑,直到在这里!

所以现在我试图找到我想出了使用LINQ,因为它是非常快的匹配标准。

result = (from x in result 
where (
    (string.Equals(x.Name, criteria)) 
    || (string.Equals(x.ID, criteria)) 
    || (x.Name.Contains(criteria)) 
    select x).ToList(); 

现在我想每个人的负载,我发现房屋和检查,如果在房子里的人的名称将匹配条件:我不比较的人它的工作原理为长。 有没有办法在LINQ中做到这一点我已经? 还是我去,虽然与结果:

result.ForEach(x => ...) 

将是很好,如果将与LINQ工作。 我做了一个类似的逻辑与

result.FindAll(new Predicate<House>((x) => { ... LoadPersons(criteria) {... } })); 

但是走上长。

亲切的问候, Asat0r

+0

你不只是试图连接在LINQ这两个项目“全价值”更容易的房屋搜索?而不是一个foreach – BugFinder

+0

房子与这个人有什么关系?你是否想将这些人“加载”到具有相同匹配标准的匹配房屋中?如果是这样,如果一个人可以匹配到多个房子呢? –

+0

House不应该在其中包含人员列表吗? – OrMiz

回答

1

。假定你有你的House一个PersonList -class你可以使用Enumerable.Any

var matchingHouses = from house in allHouses 
    where string.Equals(house.Name, criteria) 
     || string.Equals(house.ID, criteria) 
     || house.Name.Contains(criteria) 
     || house.PersonList.Any(resident => string.Equals(resident.Name, criteria)) 
    select house; 

如果返回“居民”的方法,你可以使用这个。如果以后要访问这些人,你可以创建一个匿名类型来存储他们:

var housesAndResidents = from house in allHouses 
    let matchingResidentList = LoadPersons(house.ID) 
     .Where(resident => string.Equals(resident.Name, criteria)) 
     .ToList() 
    where string.Equals(house.Name, criteria) 
     || string.Equals(house.ID, criteria) 
     || house.Name.Contains(criteria) 
     || matchingResidentList.Any() 
    select new { house, matchingResidentList }; 

您可以通过以下方式访问这些属性:

var matchingHouseList = housesAndResidents.ToList(); 
// you don't need the list, you can use foreach directly, 
// but whenever you access housesAndResidents you will execute that query 
// ToList materializes this query into a collection, so you can enumerate it or use the Count property 
foreach(var x in matchingHouseList) 
{ 
    Console.WriteLine("House:{0} Matching-Resident(s):{1}" 
     , x.house.Name 
     , String.Join(", ", x.matchingResidentList.Select(r => r.Name))); 
} 
+0

那么,这给了我一个想法,即使我没有House类中的List,“LoadPersons()”方法返回人员列表,因此我添加了: “|| LoadPersons(x.ID)。任何(y => string.Equals(y.Name,criteria))“ 因为我只能加载人员,如果我使用房屋的ID。但是这也需要一些时间。 – Asat0r

+0

@Asat0r:肯定需要一些时间,因为这个查询是昂贵的,但我不明白你可以改进它。我们对背景知之甚少,所以没有更好的建议。 –

+0

@ Asat0r:我已经展示了第二种方法,它使用该方法并将其存储为匿名类型。 –

0

下面是使用三个类的简单解决方案:ProgramHousePerson

该类House“房屋”(双关语)类Person(和你自己的价值观:名称,ID和别名)的名单。通过这种方式,居民是房子的一部分,而不是储存在其他地方。将House课外的居民储存在背包里,就像在饭盒外面放置午餐盒一样。

Person类存储关于房子的居民的基本信息。拥有House课程中的居民名单可以更轻松地将搜索标准与人员进行比较。

在类Program中,您可以找到MainFindHouses类。这些还挺解释自己

class Person 
{ 
    public string name; 
    public string alias; 

    public Person(string _name, string _alias = "") 
    { 
     name = _name; 
     alias = _alias; 
    } 
} 

class House 
{ 
    public string name; 
    public string id; 
    public string alias; 
    public List<Person> people = new List<Person>(); 

    public House(string _name, string _id, string _alias = "") 
    { 
     name = _name; 
     id = _id; 
     alias = _alias; 
    } 
} 

class Program 
{ 
    static List<House> houses = new List<House>(); 

    static void Main(string[] args) 
    { 
     // Add houses here 

     foreach (House house in FindHouses("criteria")) 
     { 
      // Do stuff 
     } 
    } 

    // Find all the houses in which the criteria exists 
    static List<House> FindHouses(string criteria) 
    { 
     // Return the list of all houses in which the criteria exists 
     return houses.Where(h => 
      h.name.Contains(criteria) || 
      h.id == criteria || 
      h.alias.Contains(criteria) || 

      h.people.Any(p => 
      p.name.Contains(criteria) || 
      p.alias.Contains(criteria))).ToList(); 
    } 
} 

我不知道这是不是太大了在你的代码的改变,但不管怎么说,我希望这有助于。

我知道你提到你不想加载到人的房屋,但是这使得基于