|
Well this is more complicated then it looks. Cause you don't know upfront how
many nested levels you have.
As each node has a list of childnodes and then each node in the nested childNodes list could have an
even deeper nested level list of childNodes ...
The only thing that comes to mind wright now is a brute force step by step actions:
1)ForEach item in the upper level list check to see if it has the id and remove it if so.
2) Else loop through the inner collection if Count>0 and remove from there else loop through it's inner collection if Count>0
and so on.
Unless you do know that there are only 2 levels.
All the best,
Dan
|
|
|
|
|
There can be any levels. I could write a recursive method, but I think that will cause problems modifying the collection.
Everything makes sense in someone's mind
|
|
|
|
|
True, a faster approach would be to use a boolean filed like obsolete/deleted/visible.
Then instead of deleting/altering the collection you would just set the value to true(no list and/or memory reallocation).
When populating UI or whatever, based on the boolean field you'll show it or not.
All the best,
Dan
|
|
|
|
|
Only if you use foreach ... it's a list so you can use integer indices. Not thread-safe but self-modification-safe:
void Remove<T>(IList<T> list, T node) where T:INested<T> {
if(list == null) return;
for(int i = list.Count; i >= 0; i--){
if(list[i] == node) list.RemoveAt(i);
else Remove(list[i].ChildNodes, node);
}
}
where
interface INested<T> { IList<T> ChildNodes; }
If this is the only place you need something like this, you don't have to generic it, but it is a general algorithm so you might want to put it in a utility library and have your class implement that interface.
|
|
|
|
|
Definition of the INested<T> interface will not compile since ChildNodes is a field. So, for testing your code, I'll be starting with this:
interface INested<T>
{
IList<T> ChildNodes { get; set; }
} In your code, where you compare:
if (list[i] == node) list.RemoveAt(i); the compiler throws an error: " Operator '==' cannot be applied to operands of type 'T' and 'T' "
best, Bill
"For no man lives in the external truth among salts and acids, but in the warm, phantasmagoric chamber of his brain, with the painted windows and the storied wall." Robert Louis Stevenson
|
|
|
|
|
I'm going to be studying this code carefully today, since it appears to me a very valuable alternative to using foreach iteration, or using Linq to kind of create a copy of the recursive data structure from which you can modify the original structure without the "modification" error.
My guess is that this (once compile-time errors are fixed) would make a great Tip/Trick for that section of CP.
thanks, Bill
"For no man lives in the external truth among salts and acids, but in the warm, phantasmagoric chamber of his brain, with the painted windows and the storied wall." Robert Louis Stevenson
modified 9-Dec-11 15:49pm.
|
|
|
|
|
I've further elaborated the idea above, using an extension method:
public interface INode<T>
where T : INode<T>
{
Guid Id { get; set; }
List<T> Children { get; set; }
}
public static class NodeExtensions
{
public static void Remove<T>(this INode<T> node, Guid id)
where T : INode<T>
{
List<T> toRemove = new List<T>();
if (node.Children == null)
return;
foreach (var child in node.Children)
{
if (child.Id == id)
toRemove.Add(child);
else
child.Remove(id);
}
foreach (var child in toRemove)
node.Children.Remove(child);
}
}
|
|
|
|
|
If the search for the item to remove did not have to be recursive: this is simpler than the other example shown in the answers here:
Folders.Remove(Folders.Find(f => f.id == model.id)); To determine whether a recursive solution is actually required, I think we need to know:
1. is the collection of Models of fixed size, or read in at one time: if it is, then, imho, creating a flattened List<folder> is the way to go: then you can use model.id to get the instance of the Model in the flattened list, and use the simple form of Folders.Remove(modelInstance), and then remove the Model from the flattened list.
2. if the collection is nested only once (a two-level tree), a simpler solution is possible using Linq. See:[^].
3. if the solution is nested to depth > 2, or has arbitrary levels of nesting, a more complex solution in Linq is possible. I suggest you look up the various solutions on StackOverFlow that use Eric Lippert's explanation ... he cites Wes Dyer[^] ... of using Linq to create a flattened hierarchy via the use of a 'Stack' .NET data structure for greatly increased efficiency. See:[^].
4. if the collection of Models is being modified, new Models are being added, etc., frequently, then paying the "cost" of synchronizing (recreating ?) the flattened List may be prohibitive. In that case, well: you just gotta recurse.
The interesting challenge in writing the recursive code in this case is how to immediately, once a matching node has been found, to delete it, and skip iterating its children, given that you can't modify the collection on the fly: which, really, is another reason to consider the use of a "parallel" flattened list, imho. Or you could extend the more common example of using Linq to essentially "temporarily copy" a List, or Dictionary, structure, and then apply the collection modifying operation to the "original" tree ?
... edit 1 ...
Bob Janova posted an interesting way, on this thread, to use a for loop and its indexes to be able to delete from a nested List structure without violating the "no modify collection injunction" found using foreach:[^].
... end edit 1 ...
... edit 2 ...
also see Marc Gravell's recursive Flattening function:[^], which is in the form of an extension.
... end edit 2 ...
Of course, I would really like to see an answer here that used Linq in some way I am not aware of to accomplish this (the depth to which I am unaware of what is possible with Linq ever-deepeningly-unfathomable)
"For no man lives in the external truth among salts and acids, but in the warm, phantasmagoric chamber of his brain, with the painted windows and the storied wall." Robert Louis Stevenson
modified 10-Dec-11 12:34pm.
|
|
|
|
|
What do you think of declaring type isomorphisms for extending the functionality of an existing class where no prior interface contract exists?
To provide a barely contrived, concrete example, let's take an Excel Interop Worksheet and a business-customized Excel export process. The existing ExcelWorksheet structurally subtypes the COM proxy and has a unified way of exporting given data of an arbitrarily defined range into a blank Worksheet. Let's say that I don't need any of the existing functionality to change, but wish to subvert the preparation of the underlying worksheet object to be replaced with a worksheet prepared outside the wrapper....and let's say that what I really want to have is a development environment where the structurally subtyped Interop proxy contained within the custom ExcelWorksheet is not treated as a property, but merely a component of the custom "ExcelWorksheet" composition...with a quick way to switch contexts from "Interop Proxy" to "Custom Wrapper around Interop proxy" with an isomorphic cast.
"I need build Skynet. Plz send code"
|
|
|
|
|
I tend to think that they're just as good an idea as any.
If you don't need to subtype the existing class, you don't need to change the way it performs its existing behavior, there's no composition model in place but need to be able to optionally rearrange the way the custom object wraps around a structurally subtyped object, I say "sure."
"I need build Skynet. Plz send code"
|
|
|
|
|
Hi every body,,
I write an app on android and i want send a string with sms to my server, because my length of string is bigger than one sms, i have to compress sms and send to my server, in my server i have a app that wrote with .net, and my problem in here!!!
I can`t find a solution for compress data in Android(Java) and decompress in C#....
Please Help......
|
|
|
|
|
whatever compression algorithm you use, IMO you're going to need two different but compatible implementations. That isn't elegant, it isn't a big deal either.
|
|
|
|
|
|
Act as a programmer: look at the one source code, then write an equivalent one in the other language. What else?
|
|
|
|
|
That`s right,, but for example we used native code, sign and unsigned numbers,, and more,,
For example , i found good algorithm in .net(http://dotnetzip.codeplex.com/[^]) ,, this lib used native code, and i have to implement this algorithm in Java that is my biiiiiiiiiiiig problem!!
So,, do you can implement a compress algorithm as same as dotnetzip in Java??
|
|
|
|
|
1. You have to work around the limitations of any particular language; e.g. if Java doesn't offer unsigned numbers, use signed ones and add some code to compensate.
2. I doubt very much a complex scheme such as Lempel-Ziv-Welch (used by ZIP) is suited for small amounts of text. IMO you have to roll your own anyway. If you can make reasonable assumptions on the input, compressing it by a factor of 2 should be quite easy. Maybe use ideas such as the ones base64 is based on.
3. Keep in mind no compression is absolute, whatever scheme (or set of schemes) you choose, there will always be inputs that don't get compressed (e.g. try putting a JPEG image in a ZIP file).
|
|
|
|
|
Thanks for attention and your time
and thanks for your guide ,,
but i tired for solved this problem,,,,,,,,
|
|
|
|
|
Hi,
In C++ I found a simple class that toggles a bool when it goes out of scope very useful.
The implementation is simple...
class CAutoBOOL
{
public:
CAutoBOOL( BOOL* pBool )
: m_pBool( pBool )
{
assert( m_pBool );
}
~CAutoBOOL()
{
*m_pBool = !(*m_pBool);
}
protected:
BOOL* m_pBool;
};
And its use is also easy...
void MyClass::foo()
{
m_bInFoo = TRUE;
CAutoBOOL ab( &m_bInFoo );
if( bDoIt )
{
return;
}
}
Whatever the code path m_bInFoo is garentied to set to FALSE when exiting Foo().
I would like to do a similar thing in C#, is it posible?
Thanks - John.
|
|
|
|
|
Member 3331570 wrote: very useful
For what? I can't think of a reason and I don't think your example helps.
As for .net in general and C# specifically, the destructor may not be called by the garbage collector for a while so I suggest a Dispose method and the using statement. But the big problem is in storing a reference to the variable, perhaps it would be easier to write a class that holds a boolean and use that instead.
public sealed class Toggler : System.IDisposable
{
public bool State { get ; set ; }
public Toggler
(
bool State
)
{
this.State = State ;
return ;
}
public void
Dispose
(
)
{
this.State = false ;
return ;
}
}
Toggler t = new Toggler ( true ) ;
using ( t )
{
System.Console.WriteLine ( t.State ) ;
}
System.Console.WriteLine ( t.State ) ;
|
|
|
|
|
Ok, I have made some progress on this.
I think I can do it using "using" as follows
MyClass::Foo()
{
using (ToggleBool tb = new ToggleBool(ref _baseControl._bReadingLog))
{
}
}
The problem I am now having is with my ToggleBool class...
class ToggleBool : IDisposable
{
public ToggleBool(ref bool bVal)
{
_bVal = bVal;
}
public void Dispose()
{
_bVal = !(bool)_bVal;
GC.SuppressFinalize(this);
}
private object _bVal;
}
It is not toggling the origional bool ref that is passed to its constructor. Is my ref, somewhere along the line becoming a value?
Or is it some other error?
Thanks - John.
|
|
|
|
|
Member 3331570 wrote: Is my ref, somewhere along the line becoming a value?
Yes, immediately when you assigned its value to _bVar.
Why are you even doing this, though? No matter what you do, it's going to be a giant hack. It already was in C++, and in C# it's going to be worse.
|
|
|
|
|
Why is it a hack? It makes my code more reliable and easy to maintain. If I introduce a new code path with a new return point, I don’t have to remember to do ‘the thing’ every time. You are not limited to toggling a bool, you could call a function, signal a synchronisation object or change the cursor. Microsoft use it in their CWaitCursor class. It’s no hack, its brilliant!
|
|
|
|
|
Well maybe. But it's "invisible logic". That something happens even if you forget it may seem nice, but it's the dirtiest possible side effect if } executes code. Combined with threading it would be the recipe for certain disaster. In C# you can't even do it without abusing using, which is meant for disposing things, not for "doing whatever".
As for MS doing it, well they can't rely on programmers doing what they're supposed to do. But if you are the programmer, certainly you can do what you tell yourself to do. You do it all the time, and forgetting to do so is called a bug.
Anyway here's a suggestion: don't have multiple return points. Problem solved.
If you really want multiple return point, you could wrap the whole thing in a try/finally. You won't have to remember "the thing" all the time (just once ... same as when using using), and the side effect is explicit.
|
|
|
|
|
So far a C# is concerned I agree, try/finaly is the best aproach.
|
|
|
|
|
You need something like this[^]. But it's a dirty hack and you should treat it accordingly.
|
|
|
|
|