我有对象国家,有区域。地区有省份。各省都有城市,城市和城市都有酒店。
我希望过滤区域列表,使其只包含属性userHaveBeenThere设置为true的对象(区域,省份,城市和酒店。
我要将此列表绑定到treeview。
这种算法情况中最糟糕的部分,例如:
区域没有userHaveBeenThere == true,所有省份也是,所有城市也是如此,但在一个城市中,十家酒店中的一家拥有userHaveBeenThere为真。 所以我必须向用户显示这个地区,只有一个省,只有一个城市,只有一家酒店。
其他可怕的事情是,我有两个树视图。起初我必须显示完整的结构,并且在第二次过滤时,所以在使用像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 :(得分:1)
你可以在你的所有对象中添加一个变量“BeenThereInHere”(或任何你想要的名字),如果他的一个孩子有userHaveBeenThere == true,那么你可以设置为true,这样你就可以快速确定扫描以及在哪里可以跳过它以节省时间。
答案 1 :(得分:1)
数据是存储在数据库中还是存储为图形?
如果是数据库,您可以设置查询以获取正确的数据。
如果是图表,您可以将其设置为双向,从底部开始(访问过的酒店),然后步行到将父项插入新对象的每个根(区域)。
答案 2 :(得分: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来表示此层次结构时,上述方法将非常有用。 您还需要在项目中包含某种字典或属性来存储计算标记。
答案 3 :(得分:1)
不要使用bool知道用户是否在那里,而是考虑使用bool?。 如果要重定向到子对象的 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 HierarchicalDatatemplate 在 TreeView 中显示您的对象。
{享受}
答案 4 :(得分: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);
}
}
我认为有很多优化:/