python expression - python

I am new in python, and while reading a BeautifulSoup tutorial, I didn't understand this expression "[x for x in titles if x.findChildren()][:-1]" that i didn't understand? can you explain it
titles = [x for x in titles if x.findChildren()][:-1]

To start with [:-1], this extracts a list that contains all elements except the last element.
>>> a=[1,2,3,4,5]
>>> a[:-1]
[1, 2, 3, 4]
The comes the first portion, that supplies the list to [:-1] (slicing in python)
[x for x in titles if x.findChildren()]
This generates a list that contains all elements (x) in the list "titles", that satisfies the condition (returns True for x.findChildren())

It's a list comprehension.
It's pretty much equivalent to:
def f():
items = []
for x in titles:
if x.findChildren():
items.append(x)
return items[:-1]
titles = f()
One of my favorite features in Python :)

The expression f(X) for X in Y if EXP is a list comprehension It will give you either a generator (if it's inside ()) or a list (if it's inside []) containing the result of evaluating f(X) for each element of Y, by only if EXP is true for that X.
In your case it will return a list containing every element from titles if the element has some children.
The ending [:-1] means, everything from the list apart from the last element.

It's called a for comprehension expression. It is simply constructing a list of all titles in the x list which return true when the findChildren function is called upon them. The final statement substracts the last one from the list.

Related

Is there a way of returning the match sublist found in the any() function?

the code is:
list_ = [[1,2,3],[4,5,6],[7,8,9]]
if i try:
1 in list_
it will return false. But if i use the any() function it returns True!
any(1 in sublist for sublist in list_)
But i want it to return the sublist that the item '1' is found. I've tried things like:
if any(1 in sublist for sublist in list_):
print(sublist)
it raise NameError: name 'sublist' is not defined
is there a way of doing it?? Thanks :)
You can use the list comprehension syntax, which includes an expression for filtering in it.
In this case, you'd want:
[sublist for sublist in list_ if 1 in sublist]
The new list will be created dynamically, and just the elements in list_ that pass the guard expression `...if 1 in sublist``` will be included.
Just to be complete: there is no way to get all the elements from a call to any because it stops processing the iterator as soon as it finds the first match - that is the advantage of using it over a regular comprehension or generator expression: the syntax for those do not allow one to stop the processing of an iterator once a condition is met.
Use an assignment expression to capture the last value evaluated by any.
if any(1 in (x := sublist) for sublist in list_):
print(x)
x is repeatedly assigned the value of sublist as any iterates the generator expression, but since any stops as soon as 1 in sublist is true, the value of x after any returns will be the value that made 1 in sublist true.
The key is that sublist is local to the generator expression itself, but x is local to the scope any executes in.
This use-case is, in fact, one of the rationales provided for the scoping of the target of an assignment expression in PEP 572.

How do I sum the first two values in each tuple in a list of tuples in Python?

I searched through stackoverflow but couldn't find an answer or adapt similar codes, unfortunately.
The problem is that I have a list of tuples:
tupl = [(5,3,33), (2,5,2), (4,1,7)]
and I should use list comprehension to have this output:
[8,7,5]
The code that I wrote is a bit dump and is:
sum_tupl = []
tupl = [(5,3,33), (2,5,2), (4,1,7)]
sum_tupl = [tupl[0][0]+tupl[0][1] for tuple in tupl]
sum_tupl
but instead of doing what I want it to do, it returns
[8,8,8]
which is the sum of the first couple executed three times.
I tried using a variant:
tupl = [(5,3,33), (2,5,2), (4,1,7)]
sum_tupl = [sum(tupl[0],tupl[1]) for tuple in tupl]
sum_tupl
(which is missing something) but to no avail.
Note: When you're beginning python, it's much easier to use loops instead of list comprehensions because then you can debug your code more easily, either by using print() statements or by stepping through it using a debugger.
Now, on to the answer:
When you do for x in y, with a list y, the individual items go in x. So for your code for tuple in tupl, you shouldn't use tupl because that is the entire list. You need to use the individual item in the list, i.e. tuple.
Note that it's not a good idea to name a variable tuple because that's already a builtin type in python.
You need:
tupl = [(5,3,33), (2,5,2), (4,1,7)]
sum_tupl = [t[0]+t[1] for t in tupl]
Which gives the list
sum_tupl: [8, 7, 5]
If you have more elements you want to sum, it makes more sense to use the sum() function and a slice of t instead of writing out everything. For example, if you wanted to sum the first 5 elements, you'd write
sum_tupl = [sum(t[0:5]) for t in tupl]
instead of
sum_tupl = [t[0]+t[1]+t[2]+t[3]+t[4] for t in tupl]
Each loop iteration you're accessing the first element of your tupl list, instead of using the current element. This is what you want:
sum_tupl = [t[0] + t[1] for t in tupl]
I prefer slicing:
>>> [x + y for x, y, *_ in tupl]
[8, 7, 5]
>>>

How to compare and remove second element of a nested list using List comprehensions?

So I have a nested list and would like to compare and remove a list inside a nested list based on the condition match.
Here is my code :
def secondValue(val):
return val[1]
if __name__ == '__main__':
nestedList=[]
for _ in range(int(input())):
name = input()
score = float(input())
nestedList.append([name,score]) # Made a nested list from the input
lowestMarks=min(nestedList,key=secondValue) [1] #Extracting the minimum score
newList=[x for x in nestedList[1] if x!=lowestMarks] # PROBLEM HERE
The last line of my code is where I want to remove the list inside my nested list based on condition match. Sure, I can do this with a nested for loop but if there is a way to do this using list comprehension I'd consider that approach.
Basically I'd appreciate an answer that tells how to remove a list from a nested list based on a condition. In my case the list looks like :
[[test,23],[test2,44],......,[testn,23]]
Problems:
for x in nestedList[1] just iterates over second sublist of the nested list.
x is a sublist and it can never be equal to lowestMarks.
Use a list-comprehension as:
newList = [[x, y] for x, y in nestedList if y != lowestMarks]
Mistake was in the below line and is now fixed.
newList=[x for x in nestedList if x[1] != lowestMarks] # PROBLEM HERE
nestedList[1] fetches the second sub-list. You want to iterate over the entire list.

How can you loop over lists of tuples where you compare the tuple in one list to the other tuples in the same list?

for x in check:
this = sorted(x) #the first tuple
for y in check:
that = sorted(y) #the other tuples in the list? in order to compare with 'this'.
if this == that:
check.remove(x)
print(check)
I basically want to check for every list (in the list 'check') if there are tuples that are the same, such as (1, 3) and (3, 1). Then I want to remove the the last one ((3,1)) out of the list 'check'. However, the function returns a "list.remove(x): x not in list" error when I use "check.remove(x)". When I used "check.remove(y)", the result was :
output of "check.remove(y)"
I noticed that the first tuple (of the tuple with the same value) got deleted and that in the second last list, that there is still a pair of tuples that have the same values.
How the list 'check' looks like
How can I compare the tuples with each other in the same list and remove the second one that contains the same values?
Repeated removal from a list is never a good a idea since it is O(N).
You can do the cleaning in one non-nested run-through, however. It is better to build a clean list from scratch and possibly reassign it to the same variable:
seen, no_dupes = set(), []
for c in check:
s = tuple(sorted(c))
if s not in seen:
seen.add(s)
no_dupes.append(c)
# check[:] = no_dupes # if you must
Use in and not ==
for x in check:
this = sorted(x) #the first tuple
for y in check:
that = sorted(y) #the other tuples in the list? in order to compare with 'this'.
if this in that:
check.remove(x)
# alternatively you might need to loop through this if its a tuple of tuples
# for t in this:
# if t in that:
# check.remove(x)
print(check)
Consider the instance [(1,1), (1,1), (1,1)]
In the first iteration, x is assigned to the first element in the list, y is also assigned to the first element, since x=y, remove x. Now when y is iterated to the second element, x=y, but now x has already been removed in the previous iteration. You should use dynamic programming:
new_check = []
for x in check:
this = sorted(x)
if x not in new_check:
new_check.append(x)
return new_check

What is an elegant way to convert the result of [x for x in y] from list to a regular variable?

What is an elegant way to convert the result of [x for x in y] from list to a regular variable?
result= [x for x in range(10) if x==7]
The result of the above will be [7].
I am now using result=result[0] but ...it does not look right :-)
thanks
You have a list comprehension on the right hand side. It evaluates to a list.
You want to pick up the first element (which is perhaps the only element for the kind of problems you are trying to solve) from it, so index the 0-th element in the list returned by the list comprehension, just like you would do it for a regular list.
result = [x for x in range(10) if x == 7][0]
You can also use a generator expression instead of a list expression and then call the next() function to retrieve the first item from the iterator returned by the generator expression.
result = next(x for x in range(10) if x == 7)
You can use next that retrieves the next object from the iterator. The parameter that goes within next is a generator. This allows saves you from fully constructing the list and then filtering for 7. Instead it only iterates until it hits 7, and wont evaluate until the next next(..) is called on the generator object.
>>> next(x for x in range(10) if x==7)
7

Categories