2016-07-28 67 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(); 
    } 
} 

我不知道這是不是太大了在你的代碼的改變,但不管怎麼說,我希望這有助於。

我知道你提到你不想加載到人的房屋,但是這使得基於