Remove sublist from DEEP nestedlist - python-3.x

I'm struggling with some NESTED LISTS.
Briefly, inside the list of lists I have some lists containing several value
biglist = [[['strings', '632'], ['otherstrings', 'hey']],[['blabla', '924'], ['histring', 'hello']]]
from this nested list, I'd like to remove the sublist in which 'hello' string appears.
I tried this:
for sub_line in big_list:
if 'hello' in sub_line:
big_list.remove(sub_line)
Now, if I print the new big_list outside the loop, I get the old list since I didn't assign the updated list to a new list. But if I assign to a new list like:
for sub_line in big_list:
if 'hello' in sub_line:
updated_list = big_list.remove(sub_line)
print(updated_list)
I get an AttributeError: 'NoneType' object has no attribute 'remove'.
So what's the problem with this?
I CANNOT use list indexing because my real list is huge and the target value is not always in the same place.
I've already check other questions but nothing is working.
Thank you all!

if you constantly have two levels of nesting (not what I would label DEEP), you could combine this answer from the dupe marking by #pault with list flattening:
biglist = [[['strings', '632'], ['otherstrings', 'hey']],[['blabla', '924'], ['histring', 'hello']]]
token = 'hello'
smalllist = [x for x in biglist if not token in [j for i in x for j in i]]
# smalllist
# Out[17]: [[['strings', '632'], ['otherstrings', 'hey']]]

Following works for me. You need to remove sub_line (not line) form the list.
big_list = [['strings', '632', 'otherstrings', 'hey'],['blabla', '924', 'histring', 'hello']]
print(big_list)
for sub_line in big_list:
if 'hello' in sub_line:
big_list.remove(sub_line)
print(big_list)

for sublist in biglist:
if 'hello' in sublist:
updated_list=biglist.remove(sublist)
print(updated_list)
The output of the above code is None because remove() does not return any value i.e, it returns None. So you should not assign return value of remove() in a list.
I think that might cause some problems whenever you will use updated_list.

Related

How do I check if a filter returns no results in Python 3?

I have a filter function that I use to clean certain items out of a list:
def filterOutPatternMatches(objList, matchKey, matchPatterns):
def checkPatterns(obj):
delete_it=True
for pat in matchPatterns:
matchString=obj[matchKey]
if pat.search(matchString):
delete_it=False
break
return delete_it
result = filter(checkPatterns, objects);
return result
It works fine, except that there is no easy way for me to find out if the filter() function has returned an empty iterable.
I want to know if the list is empty, and if so, do one thing. If not, do something else.
There are three ways to approach this:
Convert the filter object to a list, then check if it is empty:
l = list(filterObject)
if (len(l) == 0):
# The filterObject is empty, do the empty thing
The problem is that you have to convert the filterObject iterable to a list, which is potentially a very expensive operation if the iterable is very large.
Use next() to pull the first item off of the filter object iterable. If there is nothing in the list, you will get a StopIteration error, which you have to catch.
You will also need to process the first item outside of the rest, since you can't put it back on the iterable.
try:
firstItem = next(filterObject)
# Do whatever you need to do with the first item in the filterObject iterable
except StopIteration:
# Do whatever you do if there are no filter results
for o in filterObject:
# Now handle the rest of the filter results
Problems with this: you have to handle the first item outside of your for loop, which is annoying. If you want to run some aggregation function on the filterObject iterable, you have to deal with the one item that you pulled off separately. Very un-pythonic.
Iterate over the filterObject as you normally would, but set a flag if it is empty:
filterObject = filter(someFunc, someIterable)
itWasEmpty=true
for x in filterObject:
itWasEmpty=false
# Process the filterObject items
if itWasEmpty:
# Do whatever you do if it's empty.
Cons: You need to process the entire list manually. Can't pass the filter object to an aggregation function.
That's all I can come up with!

How to check if dictionary values are 'list' type?

How to check exactly if the type of value in the dictioanary are list type or not
i have list which need to check against the key's in the dictionary 'test_dict' if its exist and to know if any of values are 'list' type
col_list = ['pat_cd','dsply_nm', 'opt_cd','dsply_val']
test_dict={'pat_cd':'123','opt_cd':['232','245'],'test':['123','1232']}
result=type(any(test_dict[i]) for i in col_list if i in test_dict) is list
print(result)
##
Output
False
The out put return 'False'.. Ideally it should return 'True' since value of 'opt_cd' is list type
Can anyone help to resolve this?
Thanks
This should work:
any(isinstance(test_dict.get(k, None), list) for k in col_list)
The issue with your code is how you've used the keywords type and any. for example any works on a list of booleans. Their usage in Python is not the same as their use in English. any(test_dict[i]) will always return True so your code creates an iterator of True and an iterator is not a list. So it will always return false.
Also it is recommended to use isinstance(something,class_name) of instead of type(something) is class_name.
Although #alex's answer works. Since you're new to python I would recommend you use for loops instead. It might even help the performance if the size of your dictionary or list is large.
result = False
for k in col_list:
if isinstance(test_dict.get(k, None), list):
result=True
break
Which is almost equivalent to the one liner but more readable for a beginner.:
result = any(isinstance(test_dict.get(k, None), list) for k in col_list)

Python remove word from bigram in list without returning a new list

Just quick side question. Is there a way and if, how to remove/delete a specific word from a bigram in a list (must be the same list!) that also contains just words. E.g.
In:
x = ['Peter Parker', 'Hugo', 'Fischerman']
Task, delete Parker from that same list:
Expected output:
x as ['Peter', 'Hugo', 'Fischerman']
I tried to use xx = [x.replace('Parker, '') for x in xx]but it seems to give me a new list in the sack.
Any ideas?
list = ['Peter Parker', 'Hugo', 'Fischerman'] # initialize list
for item in range(len(list)): # loop
list[item] = list[item].replace("Parker", "").strip() # replace item nu=umber "item" with its fixed result, replacing "Parker" with nothing and stripping - this just does nothing if "Parker" is not in item number "item".
That should work, just omit the list initialization to add it wherever (and don't forget to fix the variable names!)

python selenium find_elements incorrect output

I am new to python+selenium. I am trying to return some stuff with find_elements* functions - see code below. When I ask on length of the list, I can see that the number of items is correct, however when I print the content of elements I can see that each element contains the same values and it should contains different values.
elems = browser.find_elements_by_xpath("//div[#class='some_class_name')]")
print(len(elems)) # returns correct number of items
for elem in elems:
print(elem.find_element_by_xpath("//span[#class='another_class_name']").text)
print(elem.find_element_by_xpath("//div[starts-with(#href, 'https://some_web_page_name.com/')]").get_attribute(
'data'))
print(elem.find_element_by_xpath("//div[#class='other_class_name']").text)
You should use . to reduce the scope of xpath to the current element children/grandchildren. In your case, the XPath is pointing to the first element on the page rather finding under the current elem
change code as show below
for elem in elems:
print(elem.find_element_by_xpath(".//span[#class='another_class_name']").text)
print(elem.find_element_by_xpath(".//div[starts-with(#href, 'https://some_web_page_name.com/')]").get_attribute(
'data'))
print(elem.find_element_by_xpath(".//div[#class='other_class_name']").text)
While looping or using find_element inside anther selector you have to add "." inside selector otherwise it will print same element multiple times
first_element = browser.find_elements_by_xpath("//div[#class='some_class_name')]")[0].find_element_by_xpath(".//span[#class='another_class_name']").text
In your case use following code
elems = browser.find_elements_by_xpath("//div[#class='some_class_name')]")
print(len(elems)) # returns correct number of items
for elem in elems:
print(elem.find_element_by_xpath(".//span[#class='another_class_name']").text)
print(elem.find_element_by_xpath(".//div[starts-with(#href, 'https://some_web_page_name.com/')]").get_attribute('data'))
print(elem.find_element_by_xpath(".//div[#class='other_class_name']").text)

Printing a list method return None

I am an extremely begginer learning python to tackle some biology problems, and I came across lists and its various methods. Basically, when I am running print to my variable I get None as return.
Example, trying to print a sorted list assigned to a variable
list1=[1,3,4,2]
sorted=list1.sort()
print(sorted)
I receive None as return. Shouldn't this provide me with [1,2,3,4]
However, when printing the original list variable (list1), it gives me the sorted list fine.
Because the sort() method will always return None. What you should do is:
list1=[1,3,4,2]
list1.sort()
print(list1)
Or
list1=[1,3,4,2]
list2 = sorted(list1)
print(list2)
You can sort lists in two ways. Using list.sort() and this will sort list, or new_list = sorted(list) and this will return a sorted list new_list and list will not be modified.
So, you can do this:
list1=[1,3,4,2]
sorted=sorted(list1)
print(sorted)
Or you can so this:
list1=[1,3,4,2]
list1.sort()
print(list1)

Resources