Setting the Index of a Node in VirtualStringTree? - delphi

I am trying to change the index of a node, because there are some specific nodes that at all times needs to be at the bottom of my tree. I tried to change the Node.Index, but that did not change anything. So my question is: How do I change the Index of a PVirtualNode?
Thanks! - Jeff

To change the index of node A, find the node B that has the index you want A to have, and then call Tree.MoveTo(A, B, amInsertBefore, False). B and everything after it will shift down by one to make room for A, and their Index fields will be recalculated. This works even if A doesn't yet exist in the tree (such as just after calling MakeNewNode).
If you're using Index to associate each node with its corresponding data value in a list or array, then you'll find this largely ineffective for re-ordering the displayed values.

You canot change the index of a node. Normally when using VirtualStringTree you hold your data in your own data structure separate from the tree and access the data from the events.
You can also store data directly in the nodes (using a record), but I prefer the other approach because it keeps the logic out of the tree view.
For example, you could store the data in a list and access this list in the GetText handler (you can use Node.Index). Then, if you want to reorder the items, just reorder your list and everything else will happen automatically (you might have to call Invalidate on the tree).
Pseudocode:
Initializing:
Tree.RootNodeCount := MyList.Count;
In the GetTextevent:
NodeText := MyList [Node.Index];
Reordering:
Reorder (MyList);
Tree.Invalidate;

Given that you are still using the tree view control as a container, the ideal solution offered by Smasher is not available to you.
One rather obvious solution, given that your tree view has no hierarchy (i.e. it's a list) would be to use the Sort method with your own compare function (OnCompareNodes).
The other blindingly obvious strategy would be to add the node that you want at the bottom last. If you need to add other nodes later, then insert them above the special last node with InsertNode. This simple approach will probably suffice for the problem as you have described it.

TVirtualNode is a doubly-linked list, it's not a index-based structure: you change the index of a node by removing it and adding it where you want it.
Look into DeleteNode and AddChild.

Related

Dxl view move objects

Can you move an entire object from one view to another (without deleting it in one view, load another view, create object in the new view and populate it ? If yes, can you tell me how or point me in the right direction? And also, how can i get the information from the last column, without needing to iterate though all the columns. Thanks.
Concerning the comment on using the second script in a DXL attribute:
DXL attributes do not work this way.
in a DXL attribute you would never have a loop over all objects, you only refer to a single object and you calculate a value for this object's attribute.
accept and reject work on views, DXL attributes have a content, these are different concepts.
If you want to use DXL attributes, you might have one of type boolean and use a script like
bool showMe=false
// in DXL Attributes, obj contains the currently evaluated object (not the "current" object!)
if intOf(obj."Absolute Number""") == 10 then showMe=true
if intOf(obj."Absolute Number""") > 20 then showMe=true
// the name of the DXL Attribute is stored automatically in the variable attrDXLName
obj.attrDXLName = showMe
and then you have a view with a filter that shows only these objects where the attribute's value is "true"
You need to be a bit more precise in your wording, it is unclear what you want.
In DOORS, a Module contains objects. The structure of the module determines which attributes each object has. Views are a, well, a view on these objects. A view determines which attributes of the object are shown, these are the columns shown in a view. Additionally, a view can have a filter, which determines which objects of the module are shown.
So, to answer your question, if one view of a module contains an object and another view of the same module does not show that object, you need to adopt the filter of the other view.
Your second question is about DXL, right? No, I do not know of a function that tells you the number of columns in a view, so that you can use the column (index) function to get the last column, but a small loop
Column cLast
for cLast in m do {}
// now cLast contains the last column of the current view
should not hurt. But are you sure that you really want to work with columns? Usually, scripts rather deal with attributes of objects, and only rarely with columns (the exception being dxl layout columns and of course scripts that manipulate views).
Update: to add to my comment about filters in views, there actually is a way of adding single objects to a view, i.e. the accept/reject method. You could have a script like
Object o
for o in entire current Module do {
reject o
if intOf(o."Absolute Number""") == 10 then accept o
if intOf(o."Absolute Number""") > 20 then accept o
if o."Requrement type""" == "Functional" then accept o
}
filtering on
but this addition will be very short-lived: as soon as you change the view, it forgets that sort of filtering, even if you save the view. So, again, it is not a move.

Remove item from filter list as well as from original list

I am working on UISearchBar on Swift 4.0. I have originalList[ModelItem] and filterList[ModelItem]. While in searching lets say user wants to delete on filterList 5th position which is 10th item on actual originalList. It make sense to delete this item from both of the list right? Items have no id or similar type field.
What would be the basic steps for such both-way deletion? I was looking for a general idea of achieving this.
If the model is a class and the filterList is created directly from the originalList (no new objects created, but both lists reference the same objects), then you can use this code:
let itemToDelete = filterList.remove(at: indexPath.row)
if let index = originalList.index(where: { $0 === itemToDelete }) {
originalList.remove(at: index)
}
print(originalList)
print(filterList)
=== operator will test the equality of the instances, thus identifying the proper instance to be removed from originalList.
In case you are using struct as a model, you will have to implement Equatable with some heuristics that would be able to detect if two instances are equal or not even without having an explicit identifier and then use == to find the proper instance in originalList to be removed.
Another alternative might be implementing search with index method, that would use the same filtering algorithm as your current filter method, but would take one more parameter - index in the filterList (filterIndex) along with the filter text, and based on that would compute and return an index in the originalList that matches the provided pair of filter text and filterIndex.
Yet another alternative, which I would not recommend (I would call it a hack) - you can keep a dictionary of indexes from originalList to filterList which you can use to have explicit mapping between originalList and filterList. This would however require that you always update that dictionary whatever change is made to one of the lists - every search, every deletion or removal or insertion would require an update of the mapping dictionary. This seems way to complicated and error prone.
You have a number of options.
You can maintain a mapping between the original and the filtered items positions, so you can perform deletion on both lists.
You can make your items identifiable, so you can search for the corresponding item in the original list and delete it. Note that all reference types can be tested for identity (===).
You can work with a filtered "view" to the original list, and not with a filtered copy, so the deletion will be performed on the original list naturally.
I don't think we have a standard solution for the latter option, which makes this approach the most complicated.
When choosing either of the first two options be careful with the original list updates that can happen while you operate on the filtered copy.

Can I add a where clause to a match in cypher and filter by a relationship property that is an array?

I have a linked list, in neo4j that looks something like this:
CREATE (p:Procedure {id:1})
CREATE (s1:Step {title:"Do Thing 1"})
CREATE (s2:Step {title:"Do Thing 2"})
MERGE (p)-[:FIRST_STEP {parent:[1]}]->(s1)-[:NEXT {parent:[1]}]->(s2)
Now I might create another list that contains this list, and for that to work, I'd either create a separate set of relationships with a new parent value, or I'd add the new parent id to the list of parents: e.g. parent[1,2].
Now, is it possible to do a match like this:
match (p:Procedure)-[rel:FIRST_STEP|NEXT*]->(steps)
WHERE p.id = 1 and 1 in rel.parent
return p, steps
I can do it if I put the constraint in the initial declaration of the relationship e.g. -[rel:FIRST_STEP|NEXT* {parent:1}]->, but that doesn't allow me to do the "IN" query.
Any thoughts or direction much appreciated.
Are there any expected use cases that will modify the list in some way, such as inserting, rearranging, or removing nodes? And if so, are the changes to one list meant to reflect changes to the other?
If these use cases exist, and if the list changes are meant to stay in sync with each other, single relationships with a list of parent ids makes sense (though the APOC Procedures library contains graph refactoring procedures that could handle either design).
If changes to one list aren't meant to reflect in the other list, then separate relationships per parent make the most sense.
Also, as far as I can tell there aren't easy operations to subtract elements from a list (you can use "+" to add an element, but you can't use "-"). I think you'd have to use a filter() to do this, which is a little awkward. It's easier syntactically to delete relationships entirely than to remove elements from lists on relationships, though that probably won't be a driving concern for your design choice.

In practice is Linked List addition O(N) or O(1)?

It is said that addition and deletion in a Linked List happens in constant time ie O(1) but access to elements happen in time proportional to the size of the list ie O(N). My question is how can you remove or add any element without first traversing to it ?In that case isn't addition or deletion also of the order O(N)?
Taking the example of Java , what happens when we use the api like this :
LinkedList stamps = new LinkedList();
stamps.add(new Stamp("Brazil"));
stamps.add(new Stamp("Spain"));
---
----
stamps.add(new Stamp("UnitedStates"); //say this is kth element in the list
----
stamps.add(new Stamp("India");
Then when some one does stamps.remove(k) , how can this operation happen in constant time?
Deleting items from a linked list works in constant time only if you have a pointer to the actual node on the list. If the only thing you have is the information that you want to delete the "n"th node, then there is no way to know which one it is - in which case you are required to traverse the list first, which is of course O(n).
Adding, on the other hand, always works in constant time, since it is in no way connected to the number of elements already contained by the list. In the example provided, every call to add() is O(1), not including the cost of calling the constructor of class Stamp. Adding to a linked list is simply attaching another element to its end. This is, of course, assuming that the implementation of the linked list knows which node is currently at the end of the list. If it doesn't know that, then, of course, traversal of the entire list is needed.

Best Possible algorithm to check if two linked lists are merging at any point? If so, where? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Linked list interview question
This is an interview question for which I don't have an answer.
Given Two lists, You cannot change list and you dont know the length.
Give best possible algorithm to:
Check if two lists are merging at any point?
If merging, at what point they are merging?
If I allow you to change the list how would you modify your algorithm?
I'm assuming that we are talking about simple linked lists and we can safely create a hash table of the list element pointers.
Q1: Iterate to end of both lists, If the respective last elements are the same, the lists merge at some point.
Complexity - O(N), space complexity - O(1)
Q2:
Put all elements of one list into a hash table
Iterate over 2nd list, probing the hash table for each element of the list. The first hit (if any) is the merge point, and we have the position in the 2nd list.
To get the position in the 1st list, iterate over the first list again looking for the element found in the previous step.
Time complexity - O(N). Space complexity - O(N)
Q3:
As Q1, but also reverse the direction of the list pointers.
Then iterate the reversed lists looking for the last common element - that is the merge point - and restoring the list to the original order.
Time complexity - O(N). Space complexity - O(1)
Number 1: Just iterate both and then check if they end with the same element. Thats O(n) and it cant be beaten (as it might possibly be the last element that is common, and getting there always takes O(n)).
Walk those two lists parallel by one element, add each element to Set of visited nodes (can be hash map, or simple set, you only need to check if you visited that node before). At each step check if you visited that node (if yes, then it's merging point), and add it to set of nodes if you visit it first time. Another version (as pointed by #reinier) is to walk only first list, store its nodes in Set and then only check second list against that Set. First approach is faster when your lists merge early, as you don't need to store all nodes from first list. Second is better at worst case, where both list don't merge at all, since it didn't store nodes from second list in Set
see 1.
Instead of Set, you can try to mark each node, but if you cannot modify structure, then it's not so helpful. You could also try unlink each visited node and link it to some guard node (which you check at each step if you encountered it while traversing). It saves memory for Set if list is long enough.
Traverse both the list and have a global variable for finding the number of NULL encountered . If they merge at some point there will be only 1 NULL else there will be two NULL.

Resources