max method of a list consisting of strings - python

I am wondering why the result is '4' if I write the following code:
lists = ['1','2','3','4']
print(max(lists))
lists.append(5)
print(max(lists))
I suppose that the max method of lists converts from str to int first and then gives me the max of ints in the first couple of lines, but this seems untrue if I try the next lines. Can anyone explain this?

Your list contains strings and you are appending an integer.
lists = ['1', '2', '3', '4', 5]
TypeError: '>' not supported between instances of 'str' and 'int'
If you had only strings or only int's max will do the comparison as the '>' operator will work. You need to convert the list to all strings or all ints.
lists = [int(x) for x in lists] #by list comprehension
>>> max(lists) # lists= [1, 2, 3, 4, 5]
>>> 5
lists = [str(x) for x in lists]
>>> max(lists) # lists = ['1', '2', '3', '4', '5']
>>> '5'
If you have not yet seen list comprehensions it's doing this but much faster and in a single line of code.
new_list = []
for x in lists:
x = int(x) #convert each individual term to integer objects
new_list.append(x)
lists = new_list

Actually, it doesn't give you TypeError it will return '4' for both cases below:
list = ['1', '2', '3', '4']
list = ['1', '2', '3', '4', 5]
because when comparing objects in python, str always > int that's why you are getting '4' as the max value because it is the highest value among the strings
here is an example to prove what I'm saying:
>print '1' > 5
True
>print '1' > '5'
False

You can try this:
lists = ['1','2','3','4']
print(max(list(map(int, lists))))
lists.append(5)
print(max(list(map(int, lists))))

Related

Delete even indexes out of range [duplicate]

I'm trying to remove the odd-indexed elements from my list (where zero is considered even) but removing them this way won't work because it throws off the index values.
lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
def remove_odd_elements(lst):
i=0
for element in lst:
if i % 2 == 0:
pass
else:
lst.remove(element)
i = i + 1
How can I iterate over my list and cleanly remove those odd-indexed elements?
You can delete all odd items in one go using a slice:
del lst[1::2]
Demo:
>>> lst = ['712490959', '2', '623726061', '2', '552157404', '2', '1285252944', '2', '1130181076', '2', '552157404', '3', '545600725', '0']
>>> del lst[1::2]
>>> lst
['712490959', '623726061', '552157404', '1285252944', '1130181076', '552157404', '545600725']
You cannot delete elements from a list while you iterate over it, because the list iterator doesn't adjust as you delete items. See Loop "Forgets" to Remove Some Items what happens when you try.
An alternative would be to build a new list object to replace the old, using a list comprehension with enumerate() providing the indices:
lst = [v for i, v in enumerate(lst) if i % 2 == 0]
This keeps the even elements, rather than remove the odd elements.
Since you want to eliminate odd items and keep the even ones , you can use a filter as follows :
>>>filtered_lst=list(filter(lambda x : x % 2 ==0 , lst))
this approach has the overhead of creating a new list.

How to save an element from a list as a whole after an if-statement

I want to save elements of a list as a whole in a new list.
My new task is to transform nested lists into a flat one. My plan was to take out the elements of each list and save them into a variable. And in the end to put the variables together, so that there is just a flat list at the end.
I have two problems:
The index-3 element ('99999') isn't saved as a whole in the list of the new variable. This problem is the topic of this question.
I cannot separate the nested list [66, 77, 88] from the higher list ['4', '5',[]], but this is not the topic of this question
So here is the code of the nested list and of my if statement:
nested_list = ['1', '2', '3', '99999',['4', '5',[66, 77, 88]]]
y = []
for i in nested_list:
if type(i) != (list or tuple):
y += i
print(y)
I want the index=3 element (the string '99999') be saved in the variable y as a whole string and not split into the single parts '9', '9', '9', '9', '9'
I want:
print(y)
['1', '2', '3', '99999']
I get:
print(y)
['1', '2', '3', '9', '9', '9', '9', '9']
I can't solve the problem with saving into a string (y = ' '), because than I get the result:
print(y)
12399999
and if I would transform the string to a list
y = list(y)
I get the same unwanted result
['1', '2', '3', '9', '9', '9', '9', '9']
I think the solution lies in the action code after the if-statement
y += i
Is there a command, which takes the whole element into y? I tried y += sum(i) but of course this didn't work, because
it adds up all numbers like int, floats, etc.., not strings
I don't need to add 9+9+9+9+9=45, but I need just the whole string in my new list y.
I don't know if i understand you right:
# List comprehension:
y = [x for x in nested_list if not isinstance(x, (list, tuple))]
# gives: ['1', '2', '3', '99999']
It would be the same as:
nested_list = ['1', '2', '3', '99999',['4', '5',[66, 77, 88]]]
y = []
for i in nested_list:
if not isinstance(i, (list or tuple)):
y.append(i) # This maybe your failure
print(y)
Does this help you or do you need to have all other elements also in your output list?
(i only recognized your example)
Additional if you want to iterate over all and flatten the whole list:
nested_list = ['1', '2', '3', '99999',['4', '5',[66, 77, 88]]]
y = []
def flatten_list(lst):
if isinstance(lst, (list, tuple)):
if len(lst) == 0:
return []
first, rest = lst[0], lst[1:]
return flatten_list(first) + flatten_list(rest)
else:
return [lst]
y = flatten_list(nested_list)
print(y) # ['1', '2', '3', '99999', '4', '5', 66, 77, 88]
One issue is that (list or tuple) evaluates to a boolean itself, and rather you should use isinstance for type checking
Then, try appending to the list rather than adding stings, which are iterable in themselves. For example, you could've tested [] + '9999' independently for your problem
y = []
for i in nested_list:
if isinstance(i, (list, tuple));
y.append(i)

Correcting a list with a dictionary and a subsequent .sort() command displays wrong string order

sorry for the bad title. I am new to programming and I could not come up with a better description.
So, I have this code:
umw = {'T':10, 'J':11, 'Q':12, 'K':13, 'A':14}
def card_ranks(ranks):
"Return a list of the ranks, sorted with higher first."
for i in ranks:
if i in umw:
index = ranks.index(i)
ranks[index] = str(umw[i])
ranks.sort(reverse = True)
return ranks
print(card_ranks(['A', '3', '4', 'K'])) #should output [14, 13, 4, 3]
This gives me the following result:
['4', '3', '14', '13']
clearing the "reverse = True" gives the following:
['13', '14', '3', '4']
If i do something like that:
r = card_ranks(['A', '3', '4', 'K'])
r[0] -> gives me '4'
but this doesnt work again:
print(sorted(r)) -> gives me ['4', '3', '14', '13'] all over again.
So it seems, that the .sort() command views the 13 & 14 as a unit and the 3 & 4.
Could somebody explain why that is?
Thanks alot!
You're sorting them lexicographically, as strings rather than numbers. You could convert them to integers first, or you could expand your umw dictionary:
umw = {str(i): i for i in range(2, 10)}
umw.update({'T':10, 'J':11, 'Q':12, 'K':13, 'A':14})
def card_ranks(ranks):
return sorted(ranks, key=umw.get, reverse=True)
card_ranks(['A', '3', '4', 'K'])
# ['A', 'K', '4', '3']
This uses the dict.get method as a key function to guide the sorting without changing the values being sorted.
You are sorting strings where '11' comes before '3'. The following sorted call deals with the necessary type conversion:
def card_ranks(ranks):
return sorted((umw[c] if c in umw else int(c) for c in ranks), reverse=True)
>>> card_ranks(['A', '3', '4', 'K'])
[14, 13, 4, 3]
For every string in ranks, the generator expression produces the corresponding value in the umw dict or, as fallback, turns the string into an int, such that a proper numerical, non-lexicographical comparison is possible.
It does not see them as a unit, it compares the charakter for charakter:
'1'<'3'<'4', so the ranking is '13'<'14'<'3'<'4'
You want all of them to be numbers, so change the following lines:
ranks[index] = str(umw[i])
to
ranks[index] = umw[i]
and:
print(card_ranks(['A', '3', '4', 'K']))
to
print(card_ranks(['A', 3, 4, 'K']))
Because the list elements are string that's why
while sorting its taking in account every character i.e. every digit in the number
Which means every string char is sorted by its first character and then by its next character
Which means "233" < "3" and "1111" < "233"
umw = {'T':10, 'J':11, 'Q':12, 'K':13, 'A':14}
def card_ranks(ranks):
"Return a list of the ranks, sorted with higher first."
for i in ranks:
if i in umw:
index = ranks.index(i)
ranks[index] = str(umw[i])
ranks = list(map(int, ranks)) # The line to be added
ranks.sort(reverse = True)
return ranks
print(card_ranks(['A', '3', '4', 'K'])) #sh
You need to convert the list elements to int by ranks = list(map(int, ranks)) before sorting the list
ranks[index] = str(umw[i])
You are saving the values as strings instead of integers. And it is sorting them as strings.
Try
ranks[index] = int(umw[i])

How to remove specific strings from a list

From the following list how can I remove elements ending with Text.
My expected result is a=['1,2,3,4']
My List is a=['1,2,3,4,5Text,6Text']
Should i use endswith to go about this problem?
Split on commas, then filter on strings that are only digits:
a = [','.join(v for v in a[0].split(',') if v.isdigit())]
Demo:
>>> a=['1,2,3,4,5Text,6Text']
>>> [','.join(v for v in a[0].split(',') if v.isdigit())]
['1,2,3,4']
It looks as if you really wanted to work with lists of more than one element though, at which point you could just filter:
a = ['1', '2', '3', '4', '5Text', '6Text']
a = filter(str.isdigit, a)
or, using a list comprehension (more suitable for Python 3 too):
a = ['1', '2', '3', '4', '5Text', '6Text']
a = [v for v in a if v.isdigit()]
Use str.endswith to filter out such items:
>>> a = ['1,2,3,4,5Text,6Text']
>>> [','.join(x for x in a[0].split(',') if not x.endswith('Text'))]
['1,2,3,4']
Here str.split splits the string at ',' and returns a list:
>>> a[0].split(',')
['1', '2', '3', '4', '5Text', '6Text']
Now filter out items from this list and then join them back using str.join.
try this. This works with every text you have in the end.
a=['1,2,3,4,5Text,6Text']
a = a[0].split(',')
li = []
for v in a:
try : li.append(int(v))
except : pass
print li

How do I remove hyphens from a nested list?

In the nested list:
x = [['0', '-', '3', '2'], ['-', '0', '-', '1', '3']]
how do I remove the hyphens?
x = x.replace("-", "")
gives me AttributeError: 'list' object has no attribute 'replace', and
print x.remove("-")
gives me ValueError: list.remove(x): x not in list.
x is a list of lists. replace() will substitute a pattern string for another within a string. What you want is to remove an item from a list. remove() will remove the first occurrence of an item. A simple approach:
for l in x:
while ("-" in l):
l.remove("-")
For more advanced solutions, see the following: Remove all occurrences of a value from a Python list

Categories

Resources