2010-08-10 9 views
1

У меня есть объект Страна, в которой есть области. Области имеют провинции. В провинциях есть города, а города и города - отели.Алгоритм фильтрации коллекции

Я хочу, чтобы отфильтровать список регионов, чтобы иметь только объекты с имуществом userHaveBeenThere установлен верно (районы, провинции, города и отели.

Я собираюсь связать этот список TreeView.

Худшая часть этой ситуации алгоритма, например, когда, например:

регион не имеет пользователяHaveBeenThere == true, все провинции тоже, все города тоже, но в одном городе одна из десяти гостиниц имеет userHaveBeenТребуется как истина. Итак, я должен показать пользователю этот регион, только с одной провинцией, с одним городом и только с одним отелем.

Другая страшная вещь, что у меня есть два дерева. Сначала я должен показать полную структуру и, во-вторых, отфильтровать, поэтому я немного пугаюсь о ссылках, используя эти операции фильтрации, такие как удаление.

Итак, вопрос в том, как отфильтровать этот список?

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

+0

Я использую List. Я думаю, что это проще :) – user278618

ответ

1

Вместо того, чтобы использовать логическое значение, чтобы знать, если пользователь уже существует, рекомендуется использовать логическое значение? , Установите значение null, если вы хотите перенаправить на дочерний объект userHasBeenThere.

Вот конкретный пример: волшебство происходит, когда вы установите значение true для объекта userHasBeenThere.

Вот пример шаблона:

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 HierarchicalDatatemplate, чтобы отобразить ваши объекты в окне TreeView.

{enjoy}

1

Вы можете добавить все объекты переменная «BeenThereInHere» (или любое другое имя, которое вы хотите), которое будет установлено в true, если у одного из его детей есть userHaveBeenThere == true, таким образом, вы можете быстро пригнуться, где сканировать, и где вы можете пропустить его, чтобы сэкономить время.

+0

это звучит интересно. Думаю, я мог :) – user278618

+0

Итак, что вы думаете? – user278618

+0

Затем вы храните в памяти путь дерева, с которым вы столкнулись, чтобы добраться до последнего узла. Создайте временное древовидное представление и продолжайте просматривать сканирование, чтобы заполнить дерево темпа. Затем вы получите список фильтров. – Wildhorn

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); 
      } 
     } 

Я думаю, что есть много, чтобы оптимизировать:/

Смежные вопросы