2010-08-10 99 views
1

我有對象國家,它有區域。地區有省份。省份有城市,城市和城市有酒店。篩選集合的算法

我要過濾的區域的名單與財產僅對象userHaveBeenThere設置爲true(區,省,市,和酒店。

我要綁定此列表樹視圖。

這種算法情況最糟糕的部分,例如:

region沒有userHaveBeenThere == true,所有省份也都是,所有城市都是,但是在一個城市裏有十家酒店有userHaveBeenThere as true。 所以我必須向用戶顯示該地區,只有一個省,只有一個城市,並且只有一家酒店。

其他可怕的是,我有兩個treeviews。起初,我必須展示完整的結構,並在第二次過濾時,所以在使用像remove這樣的過濾操作時,我對參考有點恐慌。

所以問題是如何過濾這個列表?

TreeView1 

Region1 
-Area1 
    -Province1 
    -City1 
    -City2 
     -Hotel1 
     -Hotel2 
     -Hotel3 
    -Province2 
    -City3 
    -City4 
     -Hotel4 
     -Hotel5 
     -Hotel6 
-Area2 
Region2 
-Area21 
    -Province21 
    -City21 
    -City22 
     -Hotel21 
     -Hotel22 
     -Hotel23 
    -Province22 
    -City23 
    -City24 
     -Hotel24 
     -Hotel25 
     -Hotel26 
-Area22 

Filtered list 
Region1 
-Area1 
    -Province1 
    -City2 
     -Hotel3 
Region2 
-Area21 
    -Province22 
    -City24 
     -Hotel24 

我不想回答如何綁定:)唯一的答案如何篩選:)

這是我的解決方案:

var copiedCountry = CloneObject(_package.Country); 


      for (int indexOfRegion = 0; indexOfRegion < copiedCountry.ListOfRegions.Count; indexOfRegion++) 
      { 
       var region = copiedCountry.ListOfRegions[indexOfRegion]; 
       if (region.ListOfProvinces.Count > 0) 
       { 
        for (int indexOfProvince = 0; indexOfProvince < region.ListOfProvinces.Count; indexOfProvince++) 
        { 
         var province = region.ListOfProvinces[indexOfProvince]; 
         if (province.ListOfCities.Count > 0) 
         { 
          for (int indexOfCity = 0; indexOfCity < province.ListOfCities.Count; indexOfCity++) 
          { 
           var city = province.ListOfCities[indexOfCity]; 
           int numberOfHotels = city.ListOfHotels.Count; 
           for (int indexOfHotel = 0; indexOfHotel < numberOfHotels; indexOfHotel++) 
           { 
            var hotel = city.ListOfHotels[indexOfHotel]; 
            if (hotel.userHaveBeenThere == false) 
            { 
             city.ListOfHotels[indexOfHotel] = null; 
            } 
           } 

           city.ListOfHotels.RemoveAll(h => h == null); 

           if (city.ListOfHotels.Where(h => h.userHaveBeenThere == true).Count() > 0) 
           { 

           } 
           else 
           { 
            if (city.userHaveBeenThere == false) 
            { 
             province.ListOfCities[indexOfCity]=null; 
            } 

           } 
          } 

          province.ListOfCities.RemoveAll(c => c == null); 

          if (province.ListOfCities.Count == 0) 
          { 
           if (province.userHaveBeenThere == false) 
           { 
            region.ListOfProvinces[indexOfProvince]=null; 
           } 
          } 



         } 
         else 
         { 
          if (province.userHaveBeenThere == false) 
          { 
           region.ListOfProvinces[indexOfProvince] = null; 
          } 
         } 
        } 

        region.ListOfProvinces.RemoveAll(p => p == null); 

        if (region.ListOfProvinces.Count == 0) 
        { 
         if (region.userHaveBeenThere == false) 
         { 
          copiedCountry.ListOfRegions[indexOfRegion]=null; 
         } 
        } 
       } 
       else 
       { 
        if (region.userHaveBeenThere == false) 
        { 
         copiedCountry.ListOfRegions[indexOfRegion]=null; 
        } 
       } 

       copiedCountry.ListOfRegions.RemoveAll(r => r == null); 
      } 


public static T CloneObject<T>(T item) 
     { 
      using (MemoryStream ms = new MemoryStream()) 
      { 

       BinaryFormatter bf = new BinaryFormatter(null, 
          new StreamingContext(StreamingContextStates.Clone)); 

       try 
       { 
        bf.Serialize(ms, item); 
       } 
       catch (Exception e) 
       { 
        throw; 
       } 


       ms.Seek(0, SeekOrigin.Begin); 


       return (T)bf.Deserialize(ms); 
      } 
     } 
+0

你可以給上,您使用的區域陣列結構本身更多的信息?它會更容易給你一個很好的答案,知道對象是如何實際表示的。 – sfossen 2010-08-10 18:10:05

+0

我使用列表。我認爲這很簡單:) – user278618 2010-08-11 06:50:37

回答

1

而不是使用一個布爾知道,如果用戶一直存在的,可以考慮使用一個布爾值? 。 當您想要重定向到子對象的userHasBeenThere時,將其設置爲null。

下面是一個具體的例子,當你將對象的userHasBeenThere設置爲true時,發生魔法。

下面是模式的一個例子:

public abstract class AUserTracker 
{ 
    private IEnumerable<AUserTracker> _children; 
    public IEnumerable<AUserTracker> Children 
    { 
     get { return _children; } 
     set { _children = value; } 
    } 

    private bool? _userHasBeenThere; 
    public bool UserHasBeenThere 
    { 
     get 
     { 
      if (_userHasBeenThere == null) 
      { 
       _userHasBeenThere = false; 
       // Uses OR operator, any child will trigger the show up. 
       foreach (AUserTracker child in Children) 
        _userHasBeenThere |= child.UserHasBeenThere; 
      } 
      return _userHasBeenThere ?? false; 
     } 
    } 
} 

這將是所有對象的基類。然後,您可以使用WPF HierarchicalDatatemplateTreeView中顯示您的對象。

{}享受

1

您可以添加到您的所有對象變量「BeenThereInHere」(或任何你想要的名字),如果他的一個子女擁有userHaveBeenThere == true,那麼它將被設置爲true,這樣,你可以快速確定要掃描的位置以及可以跳過的位置以節省時間。

+0

這聽起來很有趣。我想我可以:) – user278618 2010-08-10 17:28:42

+0

那麼,你的想法是什麼? – user278618 2010-08-10 17:40:53

+0

然後你記住你走過的樹的路徑到達最後一個節點。創建它的臨時樹視圖並繼續掃描以填充臨時樹視圖。然後你會有你的過濾列表。 – Wildhorn 2010-08-10 20:41:18

1

數據庫中的數據或存儲爲圖形?

如果是數據庫,則可以設置查詢以獲取正確的數據。

如果是圖形,可以將其設爲雙向,從底部開始(訪問酒店),然後走到每個根(區域),將父母插入新對象。

1

我會建議使用遞歸。對於節點,可以是國家,省,市,酒店做如下:

bool ShouldDisplayNode(Node n){ 
    if (n.Type == Hotel){ 
     return n.HasBeenThere; 
    } 
    bool display = false; 
    foreach (var child in n.Children){ 
     display |= ShouldDisplayNode(child); 
    } 
    return display; 
} 

我不知道確切的數據結構,但上面的方法將是非常有用的,當你將使用Composite Pattern來代表這個層次結構。 您還需要在項目中具有某種字典或屬性才能存儲計算的標誌。

0

這是我的解決方案:

var copiedCountry = CloneObject(_package.Country); 


      for (int indexOfRegion = 0; indexOfRegion < copiedCountry.ListOfRegions.Count; indexOfRegion++) 
      { 
       var region = copiedCountry.ListOfRegions[indexOfRegion]; 
       if (region.ListOfProvinces.Count > 0) 
       { 
        for (int indexOfProvince = 0; indexOfProvince < region.ListOfProvinces.Count; indexOfProvince++) 
        { 
         var province = region.ListOfProvinces[indexOfProvince]; 
         if (province.ListOfCities.Count > 0) 
         { 
          for (int indexOfCity = 0; indexOfCity < province.ListOfCities.Count; indexOfCity++) 
          { 
           var city = province.ListOfCities[indexOfCity]; 
           int numberOfHotels = city.ListOfHotels.Count; 
           for (int indexOfHotel = 0; indexOfHotel < numberOfHotels; indexOfHotel++) 
           { 
            var hotel = city.ListOfHotels[indexOfHotel]; 
            if (hotel.userHaveBeenThere == false) 
            { 
             city.ListOfHotels[indexOfHotel] = null; 
            } 
           } 

           city.ListOfHotels.RemoveAll(h => h == null); 

           if (city.ListOfHotels.Where(h => h.userHaveBeenThere == true).Count() > 0) 
           { 

           } 
           else 
           { 
            if (city.userHaveBeenThere == false) 
            { 
             province.ListOfCities[indexOfCity]=null; 
            } 

           } 
          } 

          province.ListOfCities.RemoveAll(c => c == null); 

          if (province.ListOfCities.Count == 0) 
          { 
           if (province.userHaveBeenThere == false) 
           { 
            region.ListOfProvinces[indexOfProvince]=null; 
           } 
          } 



         } 
         else 
         { 
          if (province.userHaveBeenThere == false) 
          { 
           region.ListOfProvinces[indexOfProvince] = null; 
          } 
         } 
        } 

        region.ListOfProvinces.RemoveAll(p => p == null); 

        if (region.ListOfProvinces.Count == 0) 
        { 
         if (region.userHaveBeenThere == false) 
         { 
          copiedCountry.ListOfRegions[indexOfRegion]=null; 
         } 
        } 
       } 
       else 
       { 
        if (region.userHaveBeenThere == false) 
        { 
         copiedCountry.ListOfRegions[indexOfRegion]=null; 
        } 
       } 

       copiedCountry.ListOfRegions.RemoveAll(r => r == null); 
      } 


public static T CloneObject<T>(T item) 
     { 
      using (MemoryStream ms = new MemoryStream()) 
      { 

       BinaryFormatter bf = new BinaryFormatter(null, 
          new StreamingContext(StreamingContextStates.Clone)); 

       try 
       { 
        bf.Serialize(ms, item); 
       } 
       catch (Exception e) 
       { 
        throw; 
       } 


       ms.Seek(0, SeekOrigin.Begin); 


       return (T)bf.Deserialize(ms); 
      } 
     } 

我認爲有很多優化:/