Use of max() in a list of sub-lists [duplicate] - python

I noticed a piece of code recently directly comparing two lists of integers like so:
a = [10,3,5, ...]
b = [5,4,3, ...,]
if a > b:
...
which seemed a bit peculiar, but I imagined it would return True if all of list_a's elements are larger then list_b's and False if each element is equal or list_b's elements are larger then list_a's. So I tested it:
>>> a=[3,3,3,3]
>>> b=[4,4,4,4]
>>> a>b
False
>>> b>a
True
Ok that works. As does:
>>> b = [1,1,1,1]
>>> a = [1,1,1,1]
>>> a>b
False
>>> b>a
False
but when it gets more fuzzy:
>>> a=[1,1,3,1]
>>> b=[1,3,1,1]
>>> a>b
False
>>> b>a
True
or:
>>> a=[1,3,1,1]
>>> b=[1,1,3,3]
>>> a>b
True
>>> b>a
False
the results are a bit stranger. What is python actually doing? It seems that it's returning the result in favour of the first list in which the left most element is greater then the corresponding?

From Comparing Sequences and Other Types in the Python tutorial:
The comparison uses lexicographical ordering: first the first two items are compared, and if they differ this determines the outcome of the comparison; if they are equal, the next two items are compared, and so on, until either sequence is exhausted.
See also the Wikipedia article about lexicographical order.

Since I didn't find the explanation of list/tuple comparison using "lexicographical ordering" particularly illuminating at first, here's an attempt to explain it "in my own words". First, here are some example lists that are referred to in the explanation below:
a = [1, 2, 3]
b = [1, 2, 10]
c = [1, 2, 3, 100]
d = [1, 2, 3]
e = [1, 2, 3, 4, 'a']
f = ['a', 'b', 'c']
The pair of items at each index are compared in turn. So, comparing a to b will result in 1 being compared to 1, 2 being compared to 2, and 3 being compared to 10.
The comparison of pairs will stop when either an unequal pair of items is found or--if the lists are different lengths--the end of the shorter list is reached.
For example, when comparing a and b, comparisons will stop when 3 and 10 are compared. When comparing b and c, comparisons will stop when 10 and 3 are compared.
As soon as an unequal pair is found, the overall result is the result of comparing the unequal items. This applies whether the lists are the same length or not--for example, list b is greater than list c because the 100 in c never comes into play.
For example, when comparing a to b, the overall result will be the result of comparing 3 to 10. a < b -> True because 3 is less than 10. a > b -> False because 3 is not greater than 10. a == b -> False because 3 does not equal 10.
If one of the lists is shorter and its N items are equal to the first N items of the longer list, as with a and c, the shorter list will be considered less than the longer list (so a is less than c).
Two lists will compare as equal only if they're the same length and all pairs of items compare as equal.
Note about types: if the items in a pair aren't comparable, the comparison will fail with a TypeError as usual. For example, comparing list a to f will fail when 1 is compared to 'a'. But also note that lists d and e can be compared since the 'a' in e is never compared to anything in d.

The given answers don't account for duplicates in the larger list, you can iterate over the bigger list and slice it each time to compare it with the sub list, this will maintain the order as well as account for duplicates.
This code would work:
def check_sublist(List,Sublist)
for i in range(len(List)):
if List[i:] ==Sublist:
return True
return False
Yes this is not time efficient but this is the only solution I could think since using set() would not maintain the order

Related

How this list with nested lists is being sorted, in Python? [duplicate]

I noticed a piece of code recently directly comparing two lists of integers like so:
a = [10,3,5, ...]
b = [5,4,3, ...,]
if a > b:
...
which seemed a bit peculiar, but I imagined it would return True if all of list_a's elements are larger then list_b's and False if each element is equal or list_b's elements are larger then list_a's. So I tested it:
>>> a=[3,3,3,3]
>>> b=[4,4,4,4]
>>> a>b
False
>>> b>a
True
Ok that works. As does:
>>> b = [1,1,1,1]
>>> a = [1,1,1,1]
>>> a>b
False
>>> b>a
False
but when it gets more fuzzy:
>>> a=[1,1,3,1]
>>> b=[1,3,1,1]
>>> a>b
False
>>> b>a
True
or:
>>> a=[1,3,1,1]
>>> b=[1,1,3,3]
>>> a>b
True
>>> b>a
False
the results are a bit stranger. What is python actually doing? It seems that it's returning the result in favour of the first list in which the left most element is greater then the corresponding?
From Comparing Sequences and Other Types in the Python tutorial:
The comparison uses lexicographical ordering: first the first two items are compared, and if they differ this determines the outcome of the comparison; if they are equal, the next two items are compared, and so on, until either sequence is exhausted.
See also the Wikipedia article about lexicographical order.
Since I didn't find the explanation of list/tuple comparison using "lexicographical ordering" particularly illuminating at first, here's an attempt to explain it "in my own words". First, here are some example lists that are referred to in the explanation below:
a = [1, 2, 3]
b = [1, 2, 10]
c = [1, 2, 3, 100]
d = [1, 2, 3]
e = [1, 2, 3, 4, 'a']
f = ['a', 'b', 'c']
The pair of items at each index are compared in turn. So, comparing a to b will result in 1 being compared to 1, 2 being compared to 2, and 3 being compared to 10.
The comparison of pairs will stop when either an unequal pair of items is found or--if the lists are different lengths--the end of the shorter list is reached.
For example, when comparing a and b, comparisons will stop when 3 and 10 are compared. When comparing b and c, comparisons will stop when 10 and 3 are compared.
As soon as an unequal pair is found, the overall result is the result of comparing the unequal items. This applies whether the lists are the same length or not--for example, list b is greater than list c because the 100 in c never comes into play.
For example, when comparing a to b, the overall result will be the result of comparing 3 to 10. a < b -> True because 3 is less than 10. a > b -> False because 3 is not greater than 10. a == b -> False because 3 does not equal 10.
If one of the lists is shorter and its N items are equal to the first N items of the longer list, as with a and c, the shorter list will be considered less than the longer list (so a is less than c).
Two lists will compare as equal only if they're the same length and all pairs of items compare as equal.
Note about types: if the items in a pair aren't comparable, the comparison will fail with a TypeError as usual. For example, comparing list a to f will fail when 1 is compared to 'a'. But also note that lists d and e can be compared since the 'a' in e is never compared to anything in d.
The given answers don't account for duplicates in the larger list, you can iterate over the bigger list and slice it each time to compare it with the sub list, this will maintain the order as well as account for duplicates.
This code would work:
def check_sublist(List,Sublist)
for i in range(len(List)):
if List[i:] ==Sublist:
return True
return False
Yes this is not time efficient but this is the only solution I could think since using set() would not maintain the order

All possible combinations of the items in n lists

I need to develop a list that contains all possible combinations in order of the elements in n lists. Basically I'm trying to find all the possible paths, which I will need later for another part of my program.
I've already made some simple code for two lists, but the problem is that I don't know how many inputs will the user give, so I have to guess. For the moment I've defined a function that outputs all possible combinations (1 way only, because they're paths). I've been also testing other alternatives like itertools (which I think may hold the answer to my problem), or using numpy arrays (the problem with this is that my array isn't homogeneous).
The input list may look something like this (3 dimensions):
chords = [[[1, 4, 8, 12], [1, 4, 10, 12]], [[4, 7, 13, 19], [4, 9, 13, 21]]]
My function that could generate the permutations between two lists:
def combination(list1, list2):
list = []
for x in list1:
for y in list2:
list.append([x,y])
return list
combination(chords[0], chords[1])
This function works as intended, but the problem is for example when I introduce combination(combination(chords[0], chords[1]), chords[3]), which doesn't count separately chords[0] and chords[1] (still, it works as intended).
Edit:
Okay, so like #iBug pointed out, a good way to do it is with itertools.product():
bases_chords = [ยทยทยท] #It's a three dimensional array I've filled out before
possibilities = [] #The list that will contain all the different combinations
for a in product(*bases_chords): #The asterisk means that I input everything on the list
possibilities.append(a)
print(possibilities)
print(len(possibilities)) #Just to check if the dimensions are right
itertools.product is what you're looking for. It takes multiple Iterables (lists are iterables) and produces a generator that loops over all combinations for each of them.
See example:
>>> for a, b, c in itertools.product([1, 2, 3], "abc", [True, False]):
... print(a, b, c)
...
1 a True
1 a False
1 b True
1 b False
1 c True
1 c False
2 a True
2 a False
2 b True
2 b False
2 c True
2 c False
3 a True
3 a False
3 b True
3 b False
3 c True
3 c False
>>>
So your use case would turn into:
itertools.product(*chords)

why does the statement [1,2] < [2,1] evaluate to True in python

I have recently started studying python programming language and in the process come across the following statement :
[1,2] < [2,1] evaluating to
True
I seem not to figure out how the comparison is being done internally by python.
The comparison is made item by item in each list:
>>> [1, 2] < [2, 1] # 1 < 2: because the first two items differ, comparison ends here
True
>>> [1, 2] == [1, 2] # 1 == 1 and 2 == 2
True
>>> [1, 2][0] < [2, 1][0] # 1 < 2
True
>>> [1, 2][1] > [2, 1][1] # 2 > 1
True
More about Comparing Sequences and Other Types:
Sequence objects may be compared to other objects with the same sequence type. The comparison uses lexicographical ordering: first the first two items are compared, and if they differ this determines the outcome of the comparison; if they are equal, the next two items are compared, and so on, until either sequence is exhausted. If two items to be compared are themselves sequences of the same type, the lexicographical comparison is carried out recursively. If all items of two sequences compare equal, the sequences are considered equal.
I'm sure this is a duplicate somewhere, but when you're comparing lists, the comparison is being done lexicographically by each element. Python first compares 1 to 2, the first elements of each list. This is true, so the right list is greater than the left.

Python for item in listA AND listB

This question may be very straightforward and obvious to some people, but for whatever reason I have been unable to find the answer online. I did not find my answer by tinkering with IDLE and trying to understand how it worked. How does a for loop work when multiple items are specified?
a = [1,2,3,4,5]
b = [6,7,8,9,0]
for item in a and b:
print 'why does this setup give the list b but nothing from a?'
Followup Questions:
1) What might happen with other operators, such as or and not?
2) Is this proper usage, even? If so, is it messy, unsafe, or frowned upon?
So, you have two lists:
>>> a = [1,2,3,4,5]
>>> b = [6,7,8,9,0]
... and you want to iterate over a and b. So what is a and b, exactly?
>>> a and b
[6, 7, 8, 9, 0]
That might look odd, but it's the result of two facts about Python:
Every object is either True-ish or False-ish. For example:
>>> bool(a)
True
>>> bool(b)
True
In fact, all lists except the empty list [] are True-ish.
Python uses short-circuit evaluation, which means that, for a and b, it:
Checks whether a is True-ish or False-ish
If a is False-ish, evaluates to a
If a is True-ish, evaluates to b
Following those rules, you should be able to see why a and b evaluates to [6, 7, 8, 9, 0] in your case (and following the same rules for combinations of the actual values True and False will show you that short-circuit evaluation does make sense).
If what you want to actually do is iterate trough the items in a and then those in b, you can just use the + operator to concatenate them:
>>> for item in a + b:
... print item,
...
1 2 3 4 5 6 7 8 9 0
As for your followup questions:
What might happen with other operators, such as or and not?
or's rules for short-circuit evaluation are different (you can look them up for yourself or just follow the link above), and in your case a or b evaluates to [1, 2, 3, 4, 5] (in other words, a).
not always returns True for a False-ish value and False for a True-ish value, and since you can't iterate over True or False, you'll get a TypeError.
Is this proper usage, even? If so, is it messy, unsafe, or frowned upon?
Well, there's nothing illegal about it, but as you can see, it doesn't do what you want. There are circumstances where (ab)using short-circuit evaluation to choose an iterable over which to iterate might be helpful, but this isn't one of them.
As you have discovered, for loops don't work when multiple items are specified! What you're getting is an iteration over a and b. a and b returns something True if both items are true; in this case, it's the rightmost operand, since it knows it's true. The correct way to do this is with itertools.chain:
for item in itertools.chain(a, b):
print 'now we get both lists'
The code a and b doesn't join the two lists, it performs the logical and operation. Logical and of two true values, such as lists, evaluates to the value of the second argument. If you use the or operator, it evaluates to the first non-false value. Using not will evaluate to True for a non-true value and False for a true value. Normally, using the value of an and or or as anything other than a Boolean is frowned upon.
There are several ways to accomplish what you're trying to do. The simplest would be to loop over a + b - this gives you a new list. If your lists are large, you might consider using itertools.chain() which will let you loop over all the values without creating a new list object.
This seem to be a situation where Pythons use of English words ends up being confusing. The statement for item in a and b does not mean "iterate over all items in a and then all items in b" but rater "iterate over all items in the list you get when applying the and operation on the lists a and b".
So what you are doing is the latter. You are anding the two lists a and b and then looping over the result. In the interpreter, anding a and b you get
>>> a = [1,2,3,4,5]
>>> b = [6,7,8,9,0]
>>> a and b
[6, 7, 8, 9, 0]
You can of course do this for any operations, but it is still just applied before the for loop.
To loop over both lists one after the other, replace the and operation with a + to put them together, concatenate them. Like this
>>> a + b
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
>>> for item in a + b:
... print item,
...
1 2 3 4 5 6 7 8 9 0
a and b will give b if both a and b are not None or empty or 0. Try typing 1 and 2 in Python shell.
Try:
a = [1,2,3,4,5]
b = [6,7,8,9,0]
for item in a + b:
print item
You can concatenate lists with the + operator.
You could also do:
for i in a + b:
print i
This will join the two lists and allow you to iterate through it.

Comparing two lists using the greater than or less than operator

I noticed a piece of code recently directly comparing two lists of integers like so:
a = [10,3,5, ...]
b = [5,4,3, ...,]
if a > b:
...
which seemed a bit peculiar, but I imagined it would return True if all of list_a's elements are larger then list_b's and False if each element is equal or list_b's elements are larger then list_a's. So I tested it:
>>> a=[3,3,3,3]
>>> b=[4,4,4,4]
>>> a>b
False
>>> b>a
True
Ok that works. As does:
>>> b = [1,1,1,1]
>>> a = [1,1,1,1]
>>> a>b
False
>>> b>a
False
but when it gets more fuzzy:
>>> a=[1,1,3,1]
>>> b=[1,3,1,1]
>>> a>b
False
>>> b>a
True
or:
>>> a=[1,3,1,1]
>>> b=[1,1,3,3]
>>> a>b
True
>>> b>a
False
the results are a bit stranger. What is python actually doing? It seems that it's returning the result in favour of the first list in which the left most element is greater then the corresponding?
From Comparing Sequences and Other Types in the Python tutorial:
The comparison uses lexicographical ordering: first the first two items are compared, and if they differ this determines the outcome of the comparison; if they are equal, the next two items are compared, and so on, until either sequence is exhausted.
See also the Wikipedia article about lexicographical order.
Since I didn't find the explanation of list/tuple comparison using "lexicographical ordering" particularly illuminating at first, here's an attempt to explain it "in my own words". First, here are some example lists that are referred to in the explanation below:
a = [1, 2, 3]
b = [1, 2, 10]
c = [1, 2, 3, 100]
d = [1, 2, 3]
e = [1, 2, 3, 4, 'a']
f = ['a', 'b', 'c']
The pair of items at each index are compared in turn. So, comparing a to b will result in 1 being compared to 1, 2 being compared to 2, and 3 being compared to 10.
The comparison of pairs will stop when either an unequal pair of items is found or--if the lists are different lengths--the end of the shorter list is reached.
For example, when comparing a and b, comparisons will stop when 3 and 10 are compared. When comparing b and c, comparisons will stop when 10 and 3 are compared.
As soon as an unequal pair is found, the overall result is the result of comparing the unequal items. This applies whether the lists are the same length or not--for example, list b is greater than list c because the 100 in c never comes into play.
For example, when comparing a to b, the overall result will be the result of comparing 3 to 10. a < b -> True because 3 is less than 10. a > b -> False because 3 is not greater than 10. a == b -> False because 3 does not equal 10.
If one of the lists is shorter and its N items are equal to the first N items of the longer list, as with a and c, the shorter list will be considered less than the longer list (so a is less than c).
Two lists will compare as equal only if they're the same length and all pairs of items compare as equal.
Note about types: if the items in a pair aren't comparable, the comparison will fail with a TypeError as usual. For example, comparing list a to f will fail when 1 is compared to 'a'. But also note that lists d and e can be compared since the 'a' in e is never compared to anything in d.
The given answers don't account for duplicates in the larger list, you can iterate over the bigger list and slice it each time to compare it with the sub list, this will maintain the order as well as account for duplicates.
This code would work:
def check_sublist(List,Sublist)
for i in range(len(List)):
if List[i:] ==Sublist:
return True
return False
Yes this is not time efficient but this is the only solution I could think since using set() would not maintain the order

Categories

Resources