How can I delete an element from a multidimensional array in Python? - python

I'm trying to make a tree structure on python using a multidimensional array on python. I'm using this line of code to create my list:
matrix = [[-1 for x in range(5)] for x in range(3)]
If I print the list it will return this:
[[-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1]]
This next paragraph is a small explanation of what I'm doing just in case anyone is interested or if it helps you give a more complete solution for my problem. The actual question is in the next paragraph.
The first position within the array is the key or name of the element, the second position is who is the parent node of the element, the third position tells you if the node has any children and the last two positions tell you who the predecessor and successor of the element are, if there are any.
The question starts here:
Anyway I'm also required to create a garbage collector that collects any node and its children if I were to choose to delete the node. However I don't know how to delete the entire element. I found another thread that suggested using something called pop to delete things from the multidimensional array. But from what I gathered after reading the answers the pop method only deletes an element within the list meaning it would only delete a -1 instead of deleting everything. So is there any method of deleting one lists within the list in its entirety.

pop deletes an element in a list even if that element is a list so to remove the first list in matrix you can use
matrix.pop(0)

Related

Python: what happens to memory when deleting a list element?

As for storing a list, Python seems to store a list of references to the list elements in a consecutive space in the memory. When I delete one element, e.g., del[5], does Python move all references after the deleted one one slot ahead in the memory?
del on python list work as a slice function, where it can slice sublist from a list or remove the entire list.
After the del operation list references are updated.
For more info read this link

How to efficently manage a list of elements that can either have one of it's elements removed or swapped with it's next one?

I have to build a program having two inputs (eventList, a list composed of strings that hold the type of operation and the id of the element that will undergo it, and idList, a list composed of ints, each one being the id of the element).
The two possible events are the deletion of the corresponding id, or having the id swap it's position in the idList with the following one (i.e. if the selected id is located in idList[2], it will swap value with idList[3]).
It has to pass strict tests with a set timeout and has to use dictionaries.
This is for a programmation assignment, I've alredy built this program but I can't find a way to get a decent time and pass the tester's timeouts.
I've alseo tried using lists instead of dicts, but I still can't pass some timeouts because of the time it takes to use .pop() and .index(), and I've been told the only way to pass all of them is to use dicts.
How I currently handle swaps:
def overtake(dictElement, elementId):
elementIndex = dictElement[elementId]
overtakerId = dictSearchOvertaker(dictElement, elementIndex)
dictElement[elementId], dictElement[overtakerId] = dictElement[overtakerId], dictElement[elementId]
return dictElement
How I currently handle deletions:
def eliminate(dictElement, elementId):
#elementIndex = dictElement[elementId]
del dictElement[elementId]
return dictUpdate(dictElement, elementId)
How i update the dictionary after an element is deleted:
def dictUpdate(dictElement, elementIndex):
listedDict = dictElement.items()
i = 0
for item in listedDict:
i += 1
if item[1] > elementIndex:
dictElement[item[0]] -= 1
return dictElement
I'm expected to handle a list of 200k elements where every element gets deleted one by one in 1.5 seconds, but it takes me more than 5 minutes, and even longer for a test where I get an idList with 1500 elements and every elements gets swapped with the following one untill in the end idList is reversed .
One thing that strikes me about this problem is that you're given a single list of operations and expected to return the result of doing all of them. That means you don't necessarily need to do them all one by one, and can instead do operations in a single batch that would otherwise be individually time-consuming.
Swapping two items is O(1) as long as you already know where they are. That's where a dict would come in -- a dict can help you associate one piece of information with another in such a way that you can find it in O(1) time. In this case, you want a way to find the index of an item given its id.
Deleting an item from the middle of a Python list is O(N), even if you already know its index, because internally it's an array and you need to shift everything over to take up the empty space every time you delete something that's not at the end. A naive solution is going to therefore be O(K*N), which is probably the thing the assignment is trying to get you to avoid. But nothing in the problem requires that you actually delete each item from the list one by one, just that the final result you return does not contain those items.
So, my approach would be:
Build a dict of id -> index. (This is just a single O(n) iteration over the list.)
Create an empty set to track deletions.
For each operation:
If it's a swap:
If the id is in your set, raise an exception.
Use your dict to find the indices of the two ids.
Swap the two items in the list.
Update your dict so it continues to match the list.
If it's a delete:
Add the id to your set.
Create a new list to return as the result.
For each item in the original list:
Check to see if it's in your set.
If it's in the set, skip it (it got deleted).
If not, append it to the result.
Return the result.
Where N is the list size and K is the number of operations, this ends up being O(N+K), because you iterated over the entire list of IDs exactly twice, and the entire list of operations exactly once, and everything you did inside those iterations was O(1).

Understanding selenium web-elements list

Ok so I had a list of web items created by seleniums Webdriver.find_elements_by_path method, and I had trouble utilizing the data.
Ultimately, the code I needed to get what I wanted was this:
menu_items=driver.find_elements_by_xpath('//div[#role="menuitem"]')[-2]
I was only ever able to get any meaningful data here by using a negative index. If I used any positive indices, the menu_items would return nothing.
However, when I had left menu_items as follows:
menu_items=driver.find_elements_by_xpath('//div[#role="menuitem"]')
I could iterate through the list and gain access to the webelements properly, meaning if I had"for i in menu_items" I could call something like i.text and have the desired result. But again, I could not do menu_items[2]. I am new to selenium so if someone could explain what is going on here, that would be very helpful
This line of code...
menu_items=driver.find_elements_by_xpath('//div[#role="menuitem"]')[-2]
...indicates you are considering the second element counting from the right instead of the left as list[-1] refers to the last element within the list and list[-2] refers to the second last element in the list.
A bit more about your usecase would have helped us to construct a canonical answer. The number of visible/interactable elements at any given point of time and/or the sequence in which the elements gets visible/interactable may vary based on the type of elements present in the DOM Tree. Incase the HTML DOM consists of JavaScript, Angular, ReactJS, enabled elements even the position of the elements may differ as well.

Duplicate element being added through for loop

NOTE: I do not want to use del
I am trying to understand algorithms better which is why I want to avoid the built-in del statement.
I am populating a list of 10 randomly generated numbers. I then am trying to remove an item from the list by index, using a for loop:
if remove_index < lst_size:
for value in range(remove_index, lst_size-1):
lst[value] = lst[value+1]
lst_size -= 1
Everything works fine, except that the loop is adding the last item twice. Meaning, if the 8th item has the value 4, it will add a 9th item also valued 4. I am not sure why it is doing this. I still am able to move the value at the selected index (while moving everything up), but it adds on the duplicate.
Nothing is being added to your list. It starts out with lst_size elements, and, since you don't delete any, it retains the same number by the time you're done.
If, once you've copied all the items from remove_index onwards to the previous index in the list, you want to remove the last item, then you can do so either using del or lst.pop().
At the risk of sounding flippant, this is a general rule: if you want to do something, you have to do it. Saying "I don't want to use del" won't alter that fact.
Merely decrementing lst_size will have no effect on the list - while you may be using it to store the size of your list, they are not connected, and changing one has no effect on the other.

Is there a more pythonic way to access the child elements of parents using lxml

I am poking at XBRL documents trying to get my head around how to effectively extract and use the data. One thing I have been struggling with is making sure I use the context information correctly. Below is a snippet from one of the documents I am playing with (this is from Mattel's latest 10-K)
I want to be able to efficiently collect the context key value pairs as they are important to help align the 'real' data' Here is an example of a context element
- <context id="eol_PE6050----0910-K0010_STD_0_20091231_0">
- <entity>
<identifier scheme="http://www.sec.gov/CIK">0000063276</identifier>
</entity>
- <period>
<instant>2009-12-31</instant>
</period>
</context>
When I started this I thought that if there was a parent-child relationship I should be able to get the attributes, keys, values and text of all the children directly from applying a method (?) to the parent. But the children retain their independence though they can be found from the parent. What I mean is that if the children have attributes, keys, values and or text those constructs cannot be directly accessed from the parent instead you have to determine/identify the children and from the children access the data or metadata that is needed.
I am not fully certain why this block of code is a good starting point:
from lxml import etree
test_tree=etree.parse(r'c:\temp\test_xml\mat-20091231.xml')
tree_list=[p for p in test_tree.getiterator()
so my tree_list is a list of the elements that were determined to exist in my xml file
Because there were only 664 items in my tree_list I made the very bad assumption that all of the elements within a parent were subsumed in the parent so I kept trying to access the entity, period and instant by referencing just those elements (not their children)
for each in tree_list:
if 'context' in each.tag:
contextlist.append(each)
That is I kept applying different methods to the items in the contextlist and got really frustrated. Finally while I was writing out the question I was trying to get some help figuring out what method would give me the entity and period I just decided to try
children=[c for c in contextlist[0].iterchildren()]
so my list children has all of the children from the first item in my contextlist
One of the children is the entity element, the other is the period element
Now, it should be that each of those children have a child, the entity element has an identifier child element and the period element has an instant child element
This is getting much more complicated than it seemed this morning.
I have to know the details that are reported by the context elements to correctly evaluate and operate on the real data. It seems like I have to test each of the children of the context elements Is there a faster more efficient way to get those values? Rephrased, is there a way to have some element and create a data structure that contains all of its children, and grandchildren etc without having to do a fair amount of try else statements
Once I have them I can start building a data dictionary and assign data elements to particular entries based on the context. So getting the context elements efficiently and completely is critical to my task.
Using the element-tree interface (which lxml also supports), getiterator iterates over all the nodes in the subtree rooted at the current element.
So, [list(c.getiterator()) for c in contextlist] gives you the list of lists you want (or you may want to keep c in the resulting list to avoid having to zip it with contextlist later, i.e. diretly make a list of tuples [(c, list(c.getiterator())) for c in contextlist], depending on your intended use).
Note in passing that a listcomp of the exact form [x for x in whatever] never makes much sense -- use list(whatever), instead, to turn whatever other iterable into a list.

Categories