Dictionary of recursive tree nodes - vb.net

I am batch printing through many assemblies of AutoCAD documents. I have a recursive method that goes through each drawing to verify if it has any children, and then goes into each children to see if they have any children... and so on (recursively).
It has occured that I encounter a drawing that I has already printed, and it is completely useless for me to go through that drawing and print all it's children again.
So... I wanted to build a virtual list, if you will, of the exact replica of items in my tree view. I would use it to verify if the item I'm trying to print, already exists in the virtual list, if so ... then I would just insert the KeyValue in the tree, saving a lot of time.
I figured my declaration of my dictionary would look something like this ...
Dim dic_AllAssemblies As New Dictionary(Of String, TreeNodeCollection)
I took a screenshot for an example of my treeview:
The dictionary would contain the main top item "ADF020-080A0" as it's first key, and in that key the values of all it's children would be included ... Is that even possible? It might go down 6-7 levels or even more... Can a dictionary or ... list handle that? Or is there another method that I'm not yet aware of?
ADF020-080A0
ADF020-081A0
M17981
M17981
ADF000-092AS
Etc...
Etc...

I don't know any reason that would not work. With a Dictionary you have the .ContainsKey(string) to check for a duplicate key name. If the key is found, skip it.

Related

LabVIEW - How to clear an array after each iteration in a for loop

I'm trying to clear an array after each iteration of a for loop in LabVIEW, but the way I've implemented it has the values not going directly to what I want, but it changes with previous values in other parts of the array.
It isn't shown, but this code is inside of a for-loop that iterates through another numeric array.
I know that if I get the array to clear properly after each loop iteration, this should work. How do I do that? I'm a beginner at Labview but have been coding for awhile - help is appreciated!!!
[![labview add to array][2]][2]
It looks as if you're not quite used to how LabVIEW passes data around yet. There's no need to use lots of value property nodes for the same control or indicator within one structure; if you want to use the same data in more than one place, just branch the wire. Perhaps you're thinking that a LabVIEW control or indicator is equivalent to a variable in text languages, and you need to use a property node to get or set it. Instead, think of the wire as the variable. If you want to pass the output of one operation to the input of another, just wire the output to the input.
The indicators with terminals inside your loop will be updated with new values every loop iteration, and the code inside the loop should execute faster than a human can read those values, so once the loop has finished all the outputs except the final values will be lost. Is that what you intended, or do you want to accumulate or store them in some way?
I can see that in each loop iteration you're reading two values from a config file, and the section is specified by the string value of one element of the numeric array Array. You're displaying the two values in the indicators PICKERING and SUBUNIT. If you can describe in words (or pseudocode, or a text language you're used to) what manipulation of data you're actually trying to do in the rest of this code, we may be able to make more specific suggestions.
First of all, I'm assuming that the desired order of operations is the following:
Putting the value of Pickering into Array 2
Extracting from Array 2 the values to put in Pickering 1 and Pickering 2
Putting Array 2 back to its original value
If this is the case, with your current code you can't be sure that operation 1 will be executed be fore operation 2. In fact, the order of these operations can't be pre-determined. You must force the dataflow, for example by creating a sequence structure. You will put the code related to 1 in the first frame, then code related to operation 2 in the second.
Then, to put Array 2 back to it's original value I would add a third frame, where you force an empty array into the Value property node of Array 2 (the tool you use for pickering, but as input and not as output).
The sequence structure has to be inside the for loop.
I have never used the property node Reinit to default, so I can't help you with that.
Unfortunately I can't run Labview on this PC but I hope my explanation was clear enough, if not tell me and I will try to be more specific.

Create a List of elements from a DataTable LINQ Column

I would like to know how I can convert elements of a column of a DataTable to a list of type string, grouping the elements to avoid repetition.
For example my DataTable would look like this
DataTable
and I want to make a list containing the elements of only "User" without repeating itself using LINQ.
The code I was trying to use is
InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString).ToList(Function(g) g.ToList())
But it doesn't work for me since I am new to LINQ and still have problems forming the structures.
I'd use this:
InvoiceList = InvoiceDT.AsEnumerable().Select(Function(r) r("User").ToString()).Distinct().ToList()
If you wanted a GroupBy solution it's
InvoiceList = InvoiceDT.AsEnumerable().GroupBy(Function(r) r("User").ToString()).Select(Function(g) g.Key).ToList()
Where your code went wrong was in trying to pass a delegate to ToList; it doesn't take one (and you wouldn't ToList the g either, as it's a list of data rows with all varying properties).
To reshape our IGrouping (something like a list of objects that all share the same Key, which is a property of the list that the IGrouping represents) produced by the groupby into a sequence of string Keys we Select the Key, and then ToList that
There is a lot of back and forthing between developers over things like ToList vs ToArray - some people universally use ToList because, for collections of an unknown number of elements, both list and array will grow and resize repeatedly in the same way but using ToArray requires one additional resizing step at the end to trim off any unused slots. Mostly that's trivial in terms of an overall performance consideration and should be weighed against the benefit of releasing the memory with the trim. Getting into finer details is way beyond the scope of this answer but you can read some huge blog posts about it.
I personally think it's more important to generate sensible code by calling the method that results in the relevant type depending on what you plan to do with it; I ToList if I need List functionality (add/insert/remove).. I prefer ToArray if an array suits the follow-on purposes (read/write/random access, no insert or delete), and if I'll only ever enumerate it I don't To... anything at all - I just ForEach the result of the query, which can give a bigger performance boost than anything else because it means I may not have to enumerate the entire set (if I stop early) or allocate memory all at once for doing so (if I'm writing to a socket or file)
On the use of ToString; it's worth avoiding if you think you'll fall into a pattern where you do it on every column just to get a string. If the column is already a string it's an acceptable way to get the object that DataRow.Item gives you, into a string. If the column is another type it's better to cast it:
DirectCast(r("Age"), Integer)
r.Field(Of Integer)("Age")
Thing is, it's verbose, and ugly, and intellisense doesn't help you out with writing Age or knowing it's an Int. LINQ in VB is bad enough for verbosity without pouring gas on that fire. If you're working with datatables of a known structure, it's a lot nicer if you make strongly typed ones:
Add a new file of type DataSet to your project
Open it so the design surface appears. In the properties grid call it something reasonable, such as AccountsDataSet
Right click, Add Table, call it Invoices
Right click the emppty table, Add Column, call it User
Then use it like:
Dim dt as new AccountsDataSet.InvoicesDataTable
Populate it like:
dt.AddInvoicesRow("John Smith", ... other properties here)
Query it like:
dt.Select(Function(r) r.User).Distinct()
Much nicer than accessing column names by string, and having them be objects that need casting..
Consider the dataset generator as a way to quickly, visually, create poco classes with named, typed properties
Try this
dim list as List(of string) = InvoiceDT.Rows.
Cast(of DataRow)().
Select(Function(r) r("User").ToString()).
Distinct().
ToList()
Here you cast Row collection as IEnumerable(of DataRow), rest is trivial

Blender: split object with a shape

I've got a flat object that I want to split in multiple pieces (background: I want to print it later, but the surface of my printer is not large enough). I've modeled a simple puzzle-shape:
I would like to use this shape to cut through my object, but if I use the boolean modifier, blender generates vertexes where the shape and the object intersects, but it won't cut the object since my shape got a thickness of 0:
I don't want to make my shape thicker, because otherwise it would delete something of my object...
You are able to separate the two sides of the object from each other, and then rejoin them afterwards if you need to. (This does include the use of the boolean modifier)
First, you should add the boolean modifier to the main mesh where you want it, with the 'difference' operation. Then in edit mode, as you explained before, the vertexes are created but there isn't the actual 'cut' that you were looking for.
I recreated the scenario with a plane intersecting a cube:
This is what it looks like in edit mode after having applied the boolean modifier:
Second what you can do is (after applying the boolean modifier) select the faces you want to be separated in edit mode. Then, pressing P (shortcut for separate, you can get to it by right clicking) click on 'selection' and you should have two separate objects. One of the objects will have what looks like a missing face: If you wanted two separate objects, then you just need to add a face on the object with the missing face and you can look no further. If you wanted separate parts of objects that are separate within edit mode (all together one object in object mode) then you can select the two objects and press crtl+j. Hope this helps somehwhat!
I have selected half of the cube that I want cut out (the selection does not include the face in the middle):
There are now two objects, completely seperated from each other:

Why are Binary Search Trees (BST) created using a node data structure instead of arrays?

Most examples of BSTs I have seen are of the form
Class Node {
Node left;
Node right;
Key key;
Value value;
}
But BSTs looks like a specific form of Binary Heaps with a extra constraint , namely the left child value should be less than parent value which should be less than right node value.
Binary heaps are easily implemented using arrays. Why not create BSTs using arrays making sure that this extra rule is maintained ? What are the disadvantages of doing so ?
The answer is simple: You can't just dynamically change the size of an array.
The size of an array can't just be changed afterwards. If you would use an array you'd have to enlarge it or shrink it depending on what is added or removed which would cause unnecessary overhead since you would have to copy the content from the old array to the new array whenever you do that.
Using nodes that use references or pointers allow you to just (re)assign left and right to a new element accordingly whenever you insert or set it to null (or something similar) if you remove an element which gives you a much more dynamic structure.

check if 2 linked list have the same elements regardless of order

Is there any way to check if 2 linked lists have the same elements regardless of order.
edit question:
I have fixed the code and given some more details:
this is the method that compares 2 lists
compare: object2
^ ((mylist asBag) = ((objetc2 getList) asBag)).
the method belongs to the class myClass that has a field : myLList. myList is a linkedList of type element.
I have compiled it in the workspace:
a: = element new id:1.
b:= element new id:2.
c:=element new id:3.
d: = element new id:1.
e:= element new id:2.
f:=element new id:3.
elements1 := myClass new.
elements addFirst:a.
elements addFirst:b.
elements addFirst:c.
elements2 := myClass new.
elements addFirst:d.
elements addFirst:e.
elements addFirst:f.
Transcript show: (elements1 compare:elements2).
so I am getting false.. seems like it checks for equality by reference rather than equality by value..
So I think the correct question to ask would be: how can I compare 2 Bags by value? I have tried the '=='..but it also returned false.
EDIT:
The question changed too much - I think it deserves a new question for itself.
The whole problem here is that (element new id: 1) = (element new id: 1) is giving you false. Unless it's particular class (or superclasses) redefine it, the = message is resolved comparing by identity (==) by default. That's why your code only works with a collection being compared with itself.
Test it with, for example, lists of numbers (which have the = method redefined to reflect what humans understand by numeric equality), and it will work.
You should redefine your element's class' = (and hashCode) methods for this to work.
Smalltalk handles everything by reference: all there exist is an object, which know (reference) other objects.
It would be wrong to say that two lists are equivalent if they are in different order, as the order is part of what a list means. A list without an order is what we call a bag.
The asBag message (as all of the other as<anotherCollectionType> messages) return a new collection of the named type with all the elements of the receiver. So, #(1 2 3 2) is an Array of four elements, and #(1 2 3 2) asBag is a bag containing those four elements. As it's a Bag, it doesn't have any particular order.
When you do bagA := Bag new. you are creating a new Bag instance, and reference it with bagA variable. But then you do bagA := myList asBag, so you lose the reference to the previous bag - the first assignment doesn't do anything useful in your code, as you don't use that bag.
Saying aBool ifTrue: [^true] ifFalse: [^false] has exactly the same meaning as saying ^aBool - so we prefer just to say that. And, as you only create those two new bags to compare them, you could simplify your whole method like this:
compareTo: anotherList
^ myList asBag = anotherList asBag
Read it out loud: this object (whatever it is) compares to another list if it's list without considering order is the same than the other list without order.
The name compareTo: is kind of weird for returning a boolean (containsSameElements: would be more descriptive), but you get the point much faster with this code.
Just to be precise about your questions:
1) It doesn't work because you're comparing bag1 and bag2, but just defined bagA and bagB.
2) It's not efficient to create those two extra bags just because, and to send the senseless ifTrue: message, but other way it's OK. You may implement a better way to compare the lists, but it's way better to rely on the implementation of asBag and the Bag's = message being performant.
3) I think you could see the asBag source code, but, yes, you can assume it to be something like:
Collection>>asBag
|instance|
instance := Bag new.
instance addAll: self.
^instance
And, of course, the addAll: method could be:
Collection>>addAll: anotherCollection
anotherCollection do: [ :element | self add: element ]
So, yes - it creates a new Bag with all the receiver's elements.
mgarciaisaia's answer was good... maybe too good! This may sound harsh, but I want you to succeed if you're serious about learning, so I reiterate my suggestion from another question that you pick up a good Smalltalk fundamentals textbook immediately. Depending on indulgent do-gooders to rework your nonsensical snippets into workable code is a very inefficient way to learn to program ;)
EDIT: The question has changed dramatically. The following spoke to the original three-part question, so I paraphrased the original questions inline.
Q: What is the problem? A: The problem is lack of fundamental Smalltalk understanding.
Q: Is converting to bags an efficient way to make the comparison? A: Although it's probably not efficient, don't worry about that now. In general, and especially at the beginning when you don't have a good intuition about it, avoid premature optimization - "make it work", and then only "make it fast" if justified by real-world profiling.
Q: How does #asBag work? A: The implementation of #asBag is available in the same living world as your own code. The best way to learn is to view the implementation directly (perhaps by "browsing implementors" if you aren't sure where it's defined") and answer your own question!! If you can't understand that implementation, see #1.