Get children from flat list - silverlight-4.0

I've got a flat list of items in a ObservableCollection. These items have the properties item.Id and item.Parent.Id.
I've been given the id of the parent (top level), now with this id I need to iterate through the list and find the children of this parent. Each child can only have one parent, a parent can have multiple childs.
How can I do this effectively?

You can use:
var childrenOfParent = theCollection.Where(item => item.Parent.Id == parentId);
Edit in response to comments:
Given that you have a hierarchical dataset, I would personally make a routine that checks to see if a given item has a specific item as a parent recursively, like so:
bool HasParent(Item item, int parentId)
{
if (item.Parent == null)
return false;
else if (item.Parent.Id == parentId)
return true;
else
return HasParent(item.Parent, parentId);
}
Given this, you could use:
var childrenOfParent = theCollection.Where(item => HasParnet(item, parentId));

Well I got it, however, if anyone can optimize/refactor this code into something more efficient please let me know and I'll mark your reaction as an answer. As long as I learn :).
foreach (var item in myitemlist) // first put the top level parent in the queue
{
if (parentitem.Id == item.Id)
{
filteredChildrenQueue.Enqueue(item);
}
}
while (!stillsearching)
{
if (filteredChildrenQueue.Count == 0)
{
stillsearching = true;
return;
}
FindParentChild();
}
Keep calling this method and work the first item in the queue
private void FindParentChild()
{
foreach (var item in myitemlist)
{
if (item.Parent.Id == filteredChildrenQueue.ElementAt(0).Id)
{
filteredChildrenQueue.Enqueue(item);
}
}
filteredChildrenList.Add(filteredChildrenQueue.ElementAt(0));
filteredChildrenQueue.Dequeue();
}
filteredChildrenList will contain the top level parent + all childs it contains.

Related

Nested Loop select the minimum defined value asp.net

I have a list of states, which are defined to be ordered by min to max. the sequence is the following:
Cancelled - complete - draft - reservation - reserved - ordered - confirmed
So the cancelled is the minimum state, and confirmed is the maximum state. I may have different instances with different states, so I use a for-each loop to run through all states, and select the minimum state present in the loop.
That is: if in a list I have states [complete, reserved, draft, ordered] I need to check all the values and select complete -as it appears to be the minimum state. OR
if I have [reserved, confirmed, ordered, draft, cancelled, confirmed, confirmed] I need to select the cancelled value, as it appears to be the minimum.
I am doing the following check, but it does not seem to be working:
string globstatus = " ";
foreach (var currentstatus in list)
{
if (currentstatus == "cancelled")
{
globstatus = "cancelled";
}
else
{
if (globstatus == "cancelled")
{
return globstatus;
}
else
{
if (currentstatus == "complete")
{
globstatus = "complete";
}
else
{
if (globstatus == "complete")
{
return globstatus;
}
else
{
if (currentstatus == "draft")
{
globstatus = "draft";
}
else
{
if (globstatus == "reservation")
{
return globstatus;
}
else
{
if (currentstatus == "reserved")
{
globstatus = "reserved";
}
else
{
if (globstatus == "ordered")
{
return globstatus;
}
else
{
if (currentstatus == "confirmed")
{
globstatus = "confirmed";
}
else
{
return currentstatus;
}
}
}
}
}
}
}
}
}
}
return globstatus;
What can be the best solution to achieve the desired behavior?
I find a rule of thumb helpful that if I need more than three levels of braces, I need to rethink my code. It's hard to follow, easy to make mistakes, and a nightmare to debug. I suggest that applies here - trying to follow the flow of what all those nested if..else statements is extremely difficult.
Using Enum
My preferred solution is to achieve this using an Enum, e.g.:
var list = new List<Status>
{
Status.Complete,
Status.Draft,
Status.Draft,
Status.Confirmed
};
var minStatus = (Status)list.Select(l => (int)l).Min();
// minStatus = Status.Complete
public enum Status
{
Cancelled,
Complete,
Draft,
Reservation,
Reserved,
Ordered,
Confirmed
}
How it works: by default Enums give each value a zero-based integer, i.e. Cancelled = 0, Complete = 1 and so on. You can override this with your own values if you wish (e.g. 1/2/4/8/16 if you want to combine multiple values).
I recommend using Enum types for things like this, rather than strings. It helps avoid typos, gives someone else looking at your code a clear understanding of how your program works and its flow, and represents hierarchy in a way in which simple strings don't. (For example - does 'complete' come before or after 'draft'? Without context, I imagine most people would say after, but in this case it comes before - that is much more obvious when using an Enum.)
Parse strings to Enum
However if the statuses have to be strings, you could parse them into an enum like so:
var stringList = new List<string>
{
"complete",
"draft",
"draft",
"confirmed",
"this will be ignored"
};
var statusList = new List<int>();
foreach (var str in stringList)
{
if(Enum.TryParse(typeof(Status), str, ignoreCase: true, out object? parsed) && parsed is Status status)
{
statusList.Add((int)status);
}
}
var minStatus = (Status)statusList.Min();
// minStatus = Status.Complete
However, if it's possible to refactor your code to use the Enum in the first place, that would be a better solution, and much quicker as parsing strings has an overhead that would be good to avoid.

use map function on condition in kotlin

I have a list of items and I want to edit its values before using it. I am using the map function to update each item in it. But the catch here is, I want to only update the items when the list size is 1. I want to return the list as it is if the size is larger than 1. How can I achieve this?
myList.map {
if(resources.getBoolean(R.bool.is_tablet) && it.itemList.size<6 && it.layerType == DOUBLE_LIST) {
it.layerType = SINGLE_LIST_AUTO
it.itemList.forEach {sectionItem->
sectionItem.layerType = SINGLE_LIST_AUTO
}
it
}else{
it
}
}
You can try using filter before map:
.filter { it.itemList.size == 1 }
I am assuming you want to modify the items in your list only if some conditions are met else return the same list unmodified.
You can consider using takeIf { } for this scenario if you desire to add some syntactic sugar
fun updateItemsInMyList(myList:List<SomeClass>): List<SomeClass> {
return myList
.takeIf {
// condition to modify items in your list
it.size > 1 && otherConditions
}
?.apply {
//update your items inside the list
}
?: myList // return the unmodified list if conditions are not met
}
If I understand your question correctly, you want to check if myList contains only one value else, you want update the values and return it. You could do something along the following lines,
myList.singleOrNull ?: myList.map {
if(resources.getBoolean(R.bool.is_tablet) && it.itemList.size<6 && it.layerType == DOUBLE_LIST) {
it.layerType = SINGLE_LIST_AUTO
it.itemList.forEach {sectionItem->
sectionItem.layerType = SINGLE_LIST_AUTO
}
it
}else{
it
}
}
return myList
Basically, check if there's only a single value in the list, if so, then return the value. In the case that there isn't (you get null), then you can map the value.

How to delete the largest node in Binary search Tree

I am trying to delete the largest node in binary search tree, I thougth that these code below should be able to do it but for some reason it is not. Could someone help please!
public void remove() {
Node current = root;
while(true){
Node parent = current;
current = current.getRighChild();
if (current == null){
parent.setRighChild(null);
return;
}
}
}
public void remove()
{
root = deleteMax(root);
}
private Node deleteMax(Node x ) {
if (x.getRighChild() == null)
{
return x.getLeftChild();
}
x.setRighChild(deleteMax(x.getRighChild()));
return x;
}
In your code if the right node is empty you are still deleting it. Instead of deleting the current if it is the max. Try something like this:
removeLargest() {
current = getRoot();
rightNode == null;
while (root.Right){
current == root.Right
}
if (current.left()){
rotate()
}
current.delete()
}

ExtJS TreeStore update event fire instead of create

I am using tree.Panel with TreeStore when I call
sel_node.parentNode.appendChild(node);
tree.getSampleStore().sync();
ExtJS fire event called sample store proxy: update url instead of create url what could I have done wrong?
What exact version of ExtJS4 do you use?
In my situation, with ext-4.0.7-gpl, I debugged a bit a found out that appendChild method creates a node from and object and then performs some update operations concerning the node's position in the tree, like setting next sibling, parent etc., see [1].
When syncing, the store uses getUpdatedRecords and getNewRecords [2] methods to determine which operation to run. update or create. Somehow, our appended children turn out to be updated, not created.
Note that the method doesn't check whether the children of a parent node was loaded, just pushes the new node into an empty childNodes array; after all these operations end, other children of a parent node are never shown in the tree; and if the update operation caused the serverside generation of new id, the code breaks on the line original = me.tree.getNodeById(record.getId()); - there is no such node with the old id generated on client side..
Simply put, I think it's a bug.
[1] http://docs.sencha.com/ext-js/4-0/source/NodeInterface.html#Ext-data-NodeInterface-method-appendChild
[2] http://docs.sencha.com/ext-js/4-0/source/AbstractStore.html#Ext-data-AbstractStore-method-getUpdatedRecords
Add: ExtJS 4.1 beta 2 doesn't work better for me
Update with temp solution: I hacked a bit and think I solved the issue by overriding the appendChild method of NodeInterface like below (just to set phantom property so that the record becomes created, not updated).
Please note:
1) You should include your appendChild call in the NodeInterface expand method callback, or the bug with pushing to the empty childNodes will remain: the new node will appear somewhere in the wrong place;
2) I had to override updateIndexes of the AbstractView as well, try not to do this and maybe you'll find out why;
3) there are some issues when the store tries to delete our newly created node the next time it syncs - couldn't trace it yet;
0) I am no way ExtJS or even JS guru, so feel free to correct this hack)
Ext.data.NodeInterface.oldGpv = Ext.data.NodeInterface.getPrototypeBody;
Ext.data.NodeInterface.getPrototypeBody = function(){
var ret = Ext.data.NodeInterface.oldGpv.apply(this, arguments);
ret.appendChild = function(node, suppressEvents, suppressNodeUpdate) {
var me = this,
i, ln,
index,
oldParent,
ps;
if (Ext.isArray(node)) {
for (i = 0, ln = node.length; i < ln; i++) {
me.appendChild(node[i]);
}
} else {
node = me.createNode(node);
if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
return false;
}
index = me.childNodes.length;
oldParent = node.parentNode;
if (oldParent) {
if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
return false;
}
oldParent.removeChild(node, null, false, true);
}else{
node.phantom = true;
}
if(me.isLoaded()){
index = me.childNodes.length;
if (index === 0) {
me.setFirstChild(node);
}
me.childNodes.push(node);
node.parentNode = me;
node.nextSibling = null;
me.setLastChild(node);
ps = me.childNodes[index - 1];
if (ps) {
node.previousSibling = ps;
ps.nextSibling = node;
ps.updateInfo(suppressNodeUpdate);
} else {
node.previousSibling = null;
}
node.updateInfo(suppressNodeUpdate);
}
//console.log('appendChild was called');
// I don't know what this code mean even given the comment
// in ExtJS native source, commented out
// As soon as we append a child to this node, we are loaded
//if (!me.isLoaded()) {
// me.set('loaded', true);
//}
// If this node didnt have any childnodes before, update myself
//else
//if (me.childNodes.length === 1) {
// me.set('loaded', me.isLoaded());
//}
if (suppressEvents !== true) {
me.fireEvent("append", me, node, index);
if (oldParent) {
node.fireEvent("move", node, oldParent, me, index);
}
}
return node;
}
};
return ret;
};
this is my code to add a node by values taken from a form domainForm. The form opens by clicking an icon in an actioncolumn of our tree grid:
var node = grid.store.getAt(rowIndex);
node.expand(false, function(){
var newDomain = domainForm.getValues();
newDomain.parent = {id: node.raw.id}; // i don't know whether you'll need this
var newNode = node.appendChild(newDomain);
me.store.sync();
});
and updateIndexes overrider:
Ext.override(Ext.view.AbstractView, {
updateIndexes : function(startIndex, endIndex) {
var ns = this.all.elements,
records = this.store.getRange(),
i;
startIndex = startIndex || 0;
endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length < records.length?(ns.length - 1):records.length-1) );
for(i = startIndex; i <= endIndex; i++){
ns[i].viewIndex = i;
ns[i].viewRecordId = records[i].internalId;
if (!ns[i].boundView) {
ns[i].boundView = this.id;
}
}
}
});
Had the same issue, an update to ext-4.1.0-beta-2 fixed it.
The reason might be wrong format of data that comes from the server in response to your request.
Syncronization doesn't happen. Pass 'success' key with the value of TRUE in the server response.
Hmm ... try this ...
beforeitemexpand(node, eOpts){
if (node.data.expanded) return false
}

Comparing DropDownLists

I'm having a page that contains several dropdownlists, all filled with the same values. I would like to compare them on the client as well as on the server side.
The problem is though, that the dropdownlists are generated dynamically because their quantity can vary.
Client side comparing:
<script type="text/javascript">
function CompareSelectedValues(dropDown1ID, dropDown2ID) {
var DropDownList1 = document.getElementById(dropDown1ID);
var DropDownList2 = document.getElementById(dropDown2ID);
if (DropDownList1.selectedIndex != -1 && DropDownList2.selectedIndex != -1) {
if (DropDownList1.options[DropDownList1.selectedIndex].value != DropDownList2.options[DropDownList2.selectedIndex].value)
alert('not same');
}
}
</script>
Classic server side comparing with C#:
private bool AreDropDownListValuesEqual(DropDownList ddlist1, DropDownList ddlist2)
{
// Check for invalid input or different number of items for early return
if (ddlist1 == null || ddlist2 == null || ddlist1.Items.Count != ddlist2.Items.Count)
{
return false;
}
// Check items one by one. We need a nested loop because the list could be sorted differently while having the same values!
foreach (ListItem outerItem in ddlist1.Items)
{
bool hasMatch = false;
foreach (ListItem innerItem in ddlist2.Items)
{
if (innerItem.Value == outerItem.Value && innerItem.Text == outerItem.Text)
{
hasMatch = true;
break;
}
}
if (!hasMatch)
{
return false;
}
}
// All items from ddlist1 had a match in ddlist2 and we know that the number of items is equal, so the 2 dropdownlist are matching!
return true;
}
What kind of comparison do you need? If you don't keep them in a List and that list in Session, you can never do anything with them since you add them dynamically. Add your dropdownlists where you create them (this should me when Page.IsPostBack == false) and keep that list in session. On postbacks, load your dropdowns from the list. You can compare them using the list you keep.