I know this is a dumb question because you cannot modify the loop collection while in a loop, but I do need to change it. I know I must not change the referenced objects, but I have no idea how to do this.
var orders = _orderService.GetOrders(o => !o.Deleted &&
o.OrderStatus != OrderStatus.Cancelled &&
o.OrderStatus != OrderStatus.Complete);
foreach (var order in orders)
{
if (order.PaymentStatus == PaymentStatus.Paid)
{
if (order.ShippingStatus == ShippingStatus.ShippingNotRequired || order.ShippingStatus == ShippingStatus.Delivered)
{
var tempOrder = _orderService.GetOrderById(order.Id);
SetOrderStatus(tempOrder , OrderStatus.Complete, true);
}
}
}
I always get an error.
UPDATED: I changed to this
var orders = _orderService.GetOrders(o => !o.Deleted &&
o.OrderStatus != OrderStatus.Cancelled && o.OrderStatus != OrderStatus.CompletE);
List<int> orderIndex = new List<int>();
orders.ToList().ForEach(x => orderIndex.Add(x.Id));
foreach(var index in orderIndex)
{
var order = _orderService.GetOrderById(index);
if (order.PaymentStatus == PaymentStatus.Paid)
{
if (order.ShippingStatus == ShippingStatus.ShippingNotRequired || order.ShippingStatus == ShippingStatus.Delivered)
{
SetOrderStatus(order, OrderStatus.Complete, true);
}
}
}
try
int count = orders.Count; // the length of the collect : may need a different method for different collection types.
for(int i = 0; i < count; i++)
{
var current = orders[i];
// do stuff with current.
}
use for loop instead of foreach loop
for(int i=0; i<orders.Count; i++)
{
if (orders[i].PaymentStatus == PaymentStatus.Paid)
{
if (orders[i].ShippingStatus == ShippingStatus.ShippingNotRequired || orders[i].ShippingStatus == ShippingStatus.Delivered)
{
var tempOrder = _orderService.GetOrderById(orders[i].Id);
SetOrderStatus(tempOrder , OrderStatus.Complete, true);
}
}
}
Related
I have a search query which search for all jobs in the database and than displays them in accordance to the most recent ones filtering the data by date as follows:
result = db.AllJobModel.Where(a => a.JobTitle.Contains(searchTitle) && a.locationName.Contains(searchLocation)).ToList());
result = (from app in result orderby DateTime.ParseExact(app.PostedDate, "dd/MM/yyyy", null) descending select app).ToList();
result = GetAllJobModelsOrder(result);
after that I have a method GetAllJobModelsOrder which displays jobs in order which seems to be work fine but in my case its not ordering jobs so I need to understand where I am wrong:
private List<AllJobModel> GetAllJobModelsOrder(List<AllJobModel> result)
{
var list = result.OrderBy(m => m.JobImage.Contains("job1") ? 1 :
m.JobImage.Contains("job2") ? 2 :
m.JobImage.Contains("job3") ? 3 :
m.JobImage.Contains("job4") ? 4 :
m.JobImage.Contains("job5") ? 5 :
6)
.ToList();
return list;
}
The result I get is about 10 jobs from job1 and than followed by other jobs in the same order what I would like to achieve is to filter the most recent jobs than display one job from each type of a job.
An example of the input would be as follows:
AllJobModel allJobModel = new AllJobModel
{
JobDescription = "Description",
JobImage = "Job1",
JobTitle = "title",
locationName = "UK",
datePosted = "15/06/2020",
}
The output that I get is as follows:
In where result should be mixed from different jobs.
Excepted resulta as follows a specific order of job source--1. TotalJob[0] :: 2. MonsterJob[0] :: 3. Redd[0] :: 4. TotalJob[ 1 ] :: 5. MonsterJob[ 1 ] ::6. Redd[ 1 ]:
I have tried the following solution but list data structure seems to be not stroing data in order:
private List<AllJobModel> GetAllJobModelsOrder(List<AllJobModel> result)
{
string lastItem = "";
List<AllJobModel> list = new List<AllJobModel>();
int pos = -1;
while(result.Count != 0)
{
for(int i = 0; i < result.Count; i++)
{
if(result[i].JobImage.Contains("reed") && (lastItem == "" || lastItem == "total" || lastItem == "monster"))
{
pos++;
list.Insert(pos,result[i]);
lastItem = "reed";
result.Remove(result[i]);
break;
}else if (result[i].JobImage.Contains("total") && (lastItem == "reed" || lastItem == "monster" || lastItem == "" ))
{
pos++;
list.Insert(pos, result[i]);
lastItem = "total";
result.Remove(result[i]);
break;
}else if(result[i].JobImage.Contains("monster.png") && (lastItem =="total" || lastItem == "reed" || lastItem == "" ))
{
pos++;
list.Insert(pos, result[i]);
lastItem = "monster";
result.Remove(result[i]);
break;
}else if(result[i].JobImage.Contains("reed") &&( lastItem == "reed"))
{
if(result.FirstOrDefault(a=>a.JobImage.Contains("total") || a.JobImage.Contains("monster")) != null)
{
lastItem = "total";
break;
}
else
{
pos++;
list.Insert(pos, result[i]);
lastItem = "reed";
result.Remove(result[i]);
break;
}
}
else if (result[i].JobImage.Contains("total") && (lastItem == "total"))
{
if (result.FirstOrDefault(a => a.JobImage.Contains("reed") || a.JobImage.Contains("monster")) != null)
{
lastItem = "monster";
break;
}
else
{
pos++;
list.Insert(pos, result[i]);
lastItem = "total";
result.Remove(result[i]);
break;
}
}
else if (result[i].JobImage.Contains("monster") && (lastItem == "monster"))
{
if (result.FirstOrDefault(a => a.JobImage.Contains("total") || a.JobImage.Contains("reed")) != null)
{
lastItem = "reed";
break;
}
else
{
pos++;
list.Insert(pos, result[i]);
lastItem = "monster";
result.Remove(result[i]);
break;
}
}
}
}
return list;
}
also what I found is that the value of the elements in the list is different from what its actual value. So I am not sure if this is an error with my code or with visual studio:
you can use the below concept here. I am sorting a list based on the numeric value at the end of each string value using Regex.
List<string> ls = new List<string>() { "job2", "job1", "job4", "job3" };
ls = ls.OrderBy(x => Regex.Match(x, #"\d+$").Value).ToList();
Certainly the requirement was not as straight forward as initially thought. Which is why I am offering a second solution.
Having order by and rotate the offering "Firm" in a type of priority list for a set number of times and then just display whatever comes after that requires a custom solution. If the one algorithm you have works and you are happy then great. Otherwise, I have come up with this algorithm.
private static List<AllJobModel> ProcessJobs(List<AllJobModel> l)
{
var noPriorityFirst = 2;
var orderedList = new List<AllJobModel>();
var priorityImage = new string[] { "TotalJob", "MonsterJob", "Redd" };
var gl = l.OrderBy(o => o.datePosted).GroupBy(g => g.datePosted).ToList();
foreach (var g in gl)
{
var key = g.Key;
for (int i = 0; i < noPriorityFirst; i++)
{
foreach (var j in priorityImage)
{
var a = l.Where(w => w.datePosted.Equals(key) && w.JobImage.Equals(j)).FirstOrDefault();
if (a != null)
{
orderedList.Add(a);
var ra = l.Remove(a);
}
}
}
foreach (var j in l.ToList())
{
var a = l.Where(w => w.datePosted.Equals(key)).FirstOrDefault();
if (a != null)
{
orderedList.Add(a);
var ra = l.Remove(a);
}
}
}
return orderedList;
}
To test this process I have created this Console app:
static void Main(string[] args)
{
Console.WriteLine("Start");
var l = CreateTestList();
var lJobs = ProcessJobs(l);
lJobs.ForEach(x => Console.WriteLine($"{x.datePosted} : {x.JobImage}"));
}
private static List<AllJobModel> CreateTestList()
{
var orderedList = new List<AllJobModel>();
var l = new List<AllJobModel>();
var priorityImage = new string[] { "TotalJob", "MonsterJob", "Redd" };
var rand = new Random();
var startTime = DateTime.Now;
for (int i = 0; i < 20; i++)
{
var j = rand.Next(0, priorityImage.Length);
var h = rand.Next(0, 4);
var a = new AllJobModel();
a.JobDescription = "Desc " + i;
a.JobImage = priorityImage[j];
a.JobTitle = "Title" + i;
a.locationName = "UK";
a.datePosted = startTime.AddDays(h);
l.Add(a);
}
for (int i = 0; i < 20; i++)
{
var j = rand.Next(0, priorityImage.Length);
var h = rand.Next(0, 4);
var a = new AllJobModel();
a.JobDescription = "Desc " + i;
a.JobImage = "Job " + i;
a.JobTitle = "Title" + i;
a.locationName = "UK";
a.datePosted = startTime.AddDays(h);
l.Add(a);
}
return l;
}
I have a ConcurrentDictionary of Attributes for products. These attributes have the product ID and values for the names of the attribute and any options the attribute has. I have this ConcurrentDictionary because I have threads that are created to handle each attribute in the dictionary by attribute name.
if (knownAttribute.AttributeType.Value.Equals("Product Specification"))
{
Console.WriteLine("Started a thread for: " + knownAttribute.AttributeTypeId + ", " + knownAttribute.Value);
while (true)
{
/* if (AS400SpecificationAttributes.IsEmpty && knownSpecificationBag.IsEmpty && gatherRowsTasks.All(x => x.IsCompleted))
break;*/
AS400SpecificationAttribute AS400SpecificationAttributeWork = null;
AS400SpecificationAttributeWork = knownSpecificationBag.Keys.FirstOrDefault(x => x.AttributeName == knownAttribute.Value);
if (AS400SpecificationAttributeWork != null)
{
var product = ctx.Products.FirstOrDefault(x => x.ProductNumber == AS400SpecificationAttributeWork.ProductNumber);
if (product == null)
continue;
var productAttribute = new ProductAttribute();
productAttribute.Attribute = knownAttribute;
if (AS400SpecificationAttributeWork.AttributeValue != null)
{
var knownAttributeOption = ctx.AttributeOptions.FirstOrDefault(x => x.Attribute.Equals(knownAttribute) && x.Value.Equals(AS400SpecificationAttributeWork.AttributeValue));
if (knownAttributeOption == null)
{
knownAttributeOption = new AttributeOption();
knownAttributeOption.Value = AS400SpecificationAttributeWork.AttributeValue;
knownAttributeOption.Attribute = knownAttribute;
ctx.AttributeOptions.InsertOnSubmit(knownAttributeOption);
ctx.SubmitChanges();
}
productAttribute.AttributeOption = knownAttributeOption;
productAttribute.AttributeOptionId = knownAttributeOption.Id;
}
product.ProductAttributes.Add(productAttribute);
ctx.SubmitChanges();
string tmpstr = null;
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))
Thread.Sleep(50);
}
else
{
if (tryCounter < 5)
{
tryCounter++;
Thread.Sleep(1000);
Console.WriteLine("Thread waiting for work: Product Specification:" + knownAttribute.Value);
continue;
}
else
{
int outVal;
threadTracker.TryRemove("Product Specification:" + knownAttribute.Value, out outVal);
Console.WriteLine("Closing Thread: Product Specification:" + knownAttribute.Value);
break;
}
}
Thread.Sleep(50);
}
It seems like the following Attribute element refuses to be removed.
I don't understand why. If i put it in a while(!dic.tryRemove(ele)) it will forever be stuck and never move from there.
There may be an error somewhere within the thread but I have no idea why.
This statement
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr))
will always return true or false. It won't block. That's the behavior of ConcurrentDictionary. It will return false if the key is not in the dictionary.
If you're looping while that method returns false and it's stuck, that means that the item isn't in the dictionary when the loop begins. Either it either was never in the dictionary or that another thread already removed it.
Is your intention to loop until the item is not in the dictionary?
You could try this:
if (!knownSpecificationBag.TryRemove(AS400SpecificationAttributeWork, out tmpstr)
&& !knownSpecificationBag.ContainsKey(AS400SpecificationAttributeWork))
Implement proper equals and gethashcode when using TryRemove
public override int GetHashCode()
{
return new { this.name, this.value, this.group, this.productNumber }.GetHashCode();
}
public bool Equals(AS400SpecificationAttribute other)
{
if (other == null)
return false;
return (this.ProductNumber.Equals(other.productNumber) && ((this.group != null && this.group.Equals(other.AttributeGroup)) || (this.group == null && other.AttributeGroup == null)) && ((this.name!= null && this.name.Equals(other.AttributeName)) || (this.name == null && other.AttributeName == null)) && ((this.value != null && this.value.ToUpper().Equals(other.AttributeValue.ToUpper())) || (this.value == null && other.AttributeValue == null)));
}
I have a very unique situation in which i am generating a file for which i have to use nested loops.
So for the current file i have 4 level of nested foreach (). when the data is less its performance is ok ok type still not good but when data start growing the loop grows exponentially due to nested.
Hence it is taking lot of time. Please suggest me some alternative or how can i optimize my code.
Use case:
The file i am trying to print say is having a blue print of the structure which have these nested loop, so i had to go with nesting .
Eg:
Member Details (Level 1)
Health Coverage (Level 2)
Provider Information (Level 3)
BeneFits (Level 4)
So Member details which can have multiple Health Coverage in which each health Coverage can have multiple Provider in which each Provider can have multiple benefits.
hope this help with my situation in a real time example
Level1
foreach()
{
//do some stuff
//writer.writeline();
level2
foreach()
{
//do some stuff
//writer.writeline();
level3
foreach()
{
//do some stuff
//writer.writeline();
level4
foreach()
{
//do some stuff
//writer.writeline();
}
}
}
}
Code
In the method used below writeWholeLine() , it again contain 3 nested for each loop, was not able to post the code here due to limit of character of body
private string TransactionsGeneration(StreamWriter writer, string line, int maximumCount)
{
#region Re-Generation
TransactionCounter = 0;
foreach (DataRow memRow in MemberTblMaster.Rows)
{
TransactionCounter++;
line = string.Empty; //begin of a new Transaction
//Counter
TotalLines = 0;
ST_SE_UniqueCode = 0;
// Fill the dataset based on the member id
MemberID = Convert.ToString(memRow[MEMBER_ID]).Trim();
HealthCoverageTbl = HealthCoverageTblMaster.AsEnumerable().Where(x => x.Field<string>(MEMBER_ID).Trim() == MemberID);
Associations834Tbl = Associations834TblMaster.AsEnumerable().Where(x => x.Field<string>(MEMBER_ID).Trim() == MemberID);
AddressTbl = AddressTblMaster.AsEnumerable().Where(x => x.Field<string>(MEMBER_ID).Trim() == MemberID);
GenNameInfoTbl = GenNameInfoTblMaster.AsEnumerable().Where(x => x.Field<string>(Gen_Name_ID).Trim() == memRow[Sponsor_ID].ToString().Trim() ||
x.Field<string>(Gen_Name_ID).Trim() == memRow[Payer_ID].ToString().Trim() ||
x.Field<string>(Gen_Name_ID).Trim() == memRow[TPA_Broker_ID].ToString().Trim()
);
ContactTbl = ContactTblMaster.AsEnumerable().Where(x => x.Field<string>(MEMBER_ID).Trim() == MemberID);
GenReferenceTbl = GenReferenceTblMaster.AsEnumerable().Where(x => x.Field<string>(MEMBER_ID).Trim() == MemberID);
MemberTbl = MemberTblMaster.AsEnumerable().Where(x => x.Field<string>(MEMBER_ID).Trim() == MemberID);
// Based on Health Coverage
//Provider , COB
var loopLevel1 = (from row in LoopOrder.AsEnumerable()
where row.Field<int>(HIERARCHY_LEVEL) == 1
&& !Header.Contains(row.Field<string>(LOOP_ID).Trim())
&& !Footer.Contains(row.Field<string>(LOOP_ID).Trim())
select row);
foreach (DataRow parentLoop in loopLevel1)
{
//Level 1
//TODO : Need to implement the parent loop functionality
ParentLoop = Convert.ToString(parentLoop[PARENT_LOOP]);
string loopIDofLoopOrder = parentLoop[LOOP_ID].ToString();
LoopID = loopIDofLoopOrder;
var resultLevel1 = (from row in ValidationElementAttribute.AsEnumerable()
where row.Field<string>(LoopIdSegment).Trim() == loopIDofLoopOrder
select row);
if (resultLevel1.Any())
{
int maxCount1;
if (String.IsNullOrEmpty(Convert.ToString(parentLoop[Repeat_max])))
maxCount1 = maximumCount; //Max_Repitition = NULL means infinite number of repititions allowed; no upper cap
else
maxCount1 = Convert.ToInt32(parentLoop[Repeat_max]);
for (int i = 0; i < maxCount1; i++) //until all the repititions are covered, keep repeating the same loop, else change the parent loop
{
SkipLine = false;
WriteWholeLine(line, i, resultLevel1, writer, memRow);
#region Level 2
var loopLevel2 = (from row in LoopOrder.AsEnumerable()
where row.Field<int>(HIERARCHY_LEVEL) == 2
&& row.Field<string>(PARENT_LOOP).Trim() == loopIDofLoopOrder.Trim()
select row);
foreach (DataRow level2 in loopLevel2)
{
//Level 2
// ChildLoop = Convert.ToString(level2["PARENT_LOOP"]);// 1000C
ChildLoop = Convert.ToString(level2[LOOP_ID]);// 1100C
LoopID = ChildLoop;
var resultLevel2 = (from row in ValidationElementAttribute.AsEnumerable()
where row.Field<string>(LoopIdSegment).Trim() == ChildLoop.Trim()
select row);
//var healthCoverageIdList = memberEnrollment.Select(x => x.Field<object>(Health_Coverage_ID)).Distinct().ToList();
if (resultLevel2.Any())
{
int maxCount2;
if (String.IsNullOrEmpty(Convert.ToString(level2[Repeat_max])))
maxCount2 = maximumCount;
else
maxCount2 = Convert.ToInt32(level2[Repeat_max]);
//Custom Code
// maxCount2= ChildLoop == _2300 ? healthCoverageIdList.Count : maxCount2;
for (int j = 0; j < maxCount2; j++)
{
SkipLine = false;
//Custom Code
//if (ChildLoop == "2300")
//{
// WriteWholeLine(line, j, resultLevel2, writer, memRow, memberEnrollment.Where(x => x.Field<object>(Health_Coverage_ID) == healthCoverageIdList[j]).Select(x => x));
//}
//else
//{
//WriteWholeLine(line, j, resultLevel2, writer, memRow, memberEnrollment);
//}
WriteWholeLine(line, j, resultLevel2, writer, memRow);
if (HealthCoverageTbl.Any() && HealthCoverageTbl.Count() > j)
{
HealthCoverageID = Convert.ToString(HealthCoverageTbl.ElementAt(j).Field<string>(Health_Coverage_ID)).Trim();
}
else
{
HealthCoverageID = string.Empty;
}
#region Level 3
var loopLevel3 = (from row in LoopOrder.AsEnumerable()
where row.Field<int>(HIERARCHY_LEVEL) == 3
&& row.Field<string>(PARENT_LOOP).Trim() == ChildLoop.Trim()
select row);
foreach (DataRow level3 in loopLevel3)
{
//Level 3
ChildLoopLevel3 = Convert.ToString(level3[LOOP_ID]);
LoopID = ChildLoopLevel3;
var resultLevel3 = (from row in ValidationElementAttribute.AsEnumerable()
where row.Field<string>(LoopIdSegment).Trim() == ChildLoopLevel3.Trim()
select row);
if (resultLevel3.Any())
{
CobInfoTbl = CobInfoTblMaster.AsEnumerable().Where(x => x.Field<string>(Health_Coverage_ID).Trim() == HealthCoverageID).Select(x => x);
ProviderTbl = ProviderTblMaster.AsEnumerable().Where(x => x.Field<string>(Health_Coverage_ID).Trim() == HealthCoverageID).Select(x => x);
LXcounter = 0;
int maxCount3;
if (String.IsNullOrEmpty(Convert.ToString(level3[Repeat_max])))
maxCount3 = maximumCount;
else
maxCount3 = Convert.ToInt32(level3[Repeat_max]);
for (int k = 0; k < maxCount3; k++)
{
SkipLine = false;
if (CobInfoTbl.Any() && CobInfoTbl.Count() > k)
{
CobInfoID = CobInfoTbl.ElementAt(k).Field<string>(COB_ID);
}
else
{
CobInfoID = Convert.ToString("0");
}
//Not used : uncomment if Provider ID needed.
if (ProviderTbl.Any() && ProviderTbl.Count() > k)
{
ProviderID = ProviderTbl.ElementAt(k).Field<string>(Provider_ID).Trim();
}
else
{
ProviderID = string.Empty;
}
WriteWholeLine(line, k, resultLevel3, writer, memRow);
#region Level 4
var loopLevel4 = (from row in LoopOrder.AsEnumerable()
where row.Field<int>(HIERARCHY_LEVEL) == 4
&& row.Field<string>(PARENT_LOOP).Trim() == ChildLoopLevel3.Trim()
select row);
foreach (DataRow level4 in loopLevel4)
{
//Level 4
ChildLoopLevel4 = Convert.ToString(level4[LOOP_ID]);
LoopID = ChildLoopLevel4;
var resultLevel4 = (from row in ValidationElementAttribute.AsEnumerable()
where row.Field<string>(LoopIdSegment).Trim() == ChildLoopLevel4.Trim()
select row);
if (resultLevel4.Any())
{
int maxCount4;
if (String.IsNullOrEmpty(Convert.ToString(level4[Repeat_max])))
maxCount4 = maximumCount;
else
maxCount4 = Convert.ToInt32(level4[Repeat_max]);
for (int l = 0; l < maxCount4; l++)
{
SkipLine = false;
WriteWholeLine(line, l, resultLevel4, writer, memRow);
}
}
}
#endregion
}
}
}
#endregion
}
}
}
#endregion
}
}
}
// TODO : remove below break
// break;
}
//end of Regeneration
#endregion
return line;
}
if the order of the entries does not matter as in the results of each nested loop dont need to have the structure the foreach source has.
A->B->C->D->E each of those represent a nested loop, you could do it in parallel.
since all data manipulation should be the same, rewrite all foreach as in parallel. save the results to a collection like a ConcurrentDictionary
Here, Space is a class with (xposition, yposition, zposition, length, depth, height) as its elements and there is a list of type space.
I need to check with in the list whether it follows some conditions which are in if condition.
If it satisfies, then I merge the two spaces into single space. After that, I remove both the spaces which I have used. It actually means merging of two spaces into single space.
The new List is created. Again I treat it as new list and do the same procedure until it does not satisfies the conditions.
My problem is, it is going into infinite loop. I want to resolve this.
public class MergeSpace
{
public List<Space> Mergespace(List<Space> Listofspaces)
{
foreach (Space space1 in Listofspaces)
{
foreach (Space space2 in Listofspaces)
{
//int count = 0;
if ((space1.sheight == space2.sheight)
&& (space1.sdepth == space2.sdepth)
&& (space2.xposition == space1.xposition + space1.slength)
&& (space2.yposition == space1.yposition)
&& (space2.zposition == space1.zposition)
&& (space1.semptyspace == true)
&& (space2.semptyspace == true))
{
Space space = new Space();
space.xposition = space1.xposition;
space.yposition = space1.yposition;
space.zposition = space1.zposition;
space1.slength = space1.slength + space2.slength;
space.sheight = space1.sheight;
space.sdepth = space1.sdepth;
space.semptyspace = true;
Listofspaces.Add(space);
Listofspaces.Remove(space1);
Listofspaces.Remove(space2);
Mergespace(Listofspaces);
}
public class MergeSpace
{
public List<Space> Mergespace(List<Space> Listofspaces)
{
List<Space> mergedspacelist = new List<Space>();
int count=0;
foreach (Space space1 in Listofspaces)
{
foreach (Space space2 in Listofspaces)
{
//int count = 0;
if ((space1.sheight == space2.sheight)
&& (space1.sdepth == space2.sdepth)
&& (space2.xposition == space1.xposition + space1.slength)
&& (space2.yposition == space1.yposition)
&& (space2.zposition == space1.zposition)
&& (space1.semptyspace == true)
&& (space2.semptyspace == true))
{
Space space = new Space();
space.xposition = space1.xposition;
space.yposition = space1.yposition;
space.zposition = space1.zposition;
space1.slength = space1.slength + space2.slength;
space.sheight = space1.sheight;
space.sdepth = space1.sdepth;
space.semptyspace = true;
mergedspacelist .Add(space);
count++;
}
}
}
if(count>0)
{
Mergespace(mergedspacelist );
}
}
i dont know what your actual need is, i think this will avoid the infinite loop
Your conditions always will satisfy for same instance of Space. The instance will merge with itself.
if (!space1.Equals(space2))
{
if ((space1.sheight == space2.sheight)
...
}
I want to create a Property which can find the depth of the nested tree structure. The below static finds out the depth/level by recursion. But is it possible to make this function as a property in the same class instead of a static method?
public static int GetDepth(MenuGroup contextMenuItems)
{
if (contextMenuItems == null || contextMenuItems.Items.Count == 0)
return 0;
var subMenu = contextMenuItems.Items.Select(b => b as MenuGroup);
if (!subMenu.Any())
return 1;
var subLevel = subMenu.Cast<MenuGroup>().Select(GetDepth);
return !subLevel.Any() ? 1 : subLevel.Max() + 1;
}
Some more info on the code:
MenuGroup and MenuItem are derived from MenuBase
MenuGroup has children nodes with ObservableCollection<MenuBase> Items as Child Elements
MenuItem is a leave node without any child.
Well you could easily turn it into an instance property, yes:
public int Depth
{
get
{
if (Items.Count == 0)
return 0;
var subMenu = Items.Select(b => b as MenuGroup);
if (!subMenu.Any())
return 1;
var subLevel = subMenu.Cast<MenuGroup>().Select(x = > x.Depth);
return !subLevel.Any() ? 1 : subLevel.Max() + 1;
}
}
That won't quite work yet due to the handling of non-MenuGroup items, but it can easily be fixed, using OfType instead of the Select and then Cast:
public int Depth
{
get
{
// Completely empty menu (not even any straight items). 0 depth.
if (Items.Count == 0)
{
return 0;
}
// We've either got items (which would give us a depth of 1) or
// items and groups, so find the maximum depth of any subgroups,
// and add 1.
return Items.OfType<MenuGroup>()
.Select(x => x.Depth)
.DefaultIfEmpty() // 0 if we have no subgroups
.Max() + 1;
}
}
public string GenerateMenu()
{
StringBuilder sb = new StringBuilder();
sb.Append("<nav id=\"nvMenu\" class=\"main-nav\"><ul>");
sb.Append(PrepareMenuUL(AppConfig._AppConfigInstance.Navigation.FirstOrDefault().NavigationClass));
sb.Append("</ul></nav>");
return sb.ToString();
}
private string PrepareMenuUL(List<Navigation> navigation)
{
StringBuilder sb = new StringBuilder();
if (Liflag == 1)
{
sb.Append("</li>");
Liflag = 0;
}
foreach (var item in navigation)
{
var subMenu = item.NavigationClass.Select(b => b as Navigation);
if (subMenu.Any())
{
sb.Append("<li class=\"dropdown\">");
if (subMenu.Any() && item.Url == "#")
sb.Append(string.Format("{1}<i class=\"icon-arrow\"></i>", BaseUrl + item.Url, item.Name));
else if (subMenu.Any() && item.Url != "#" && item.Url != null)
sb.Append(string.Format("{1}<i class=\"icon-rightarrow\"></i>", BaseUrl + item.Url, item.Name));
}
else
{
sb.Append("<li>");
sb.Append(string.Format("{1}", BaseUrl + item.Url, item.Name));
}
if (subMenu.Any())
sb.Append("<ul class=\"wd190\">");
if (item.NavigationClass.Count > 0)
{
Liflag = 1;
sb.Append(PrepareMenuUL(item.NavigationClass));
}
sb.Append("</li>");
if (subMenu.Any())
sb.Append("</ul>");
}
return sb.ToString();
}