Python: finding lowest integer - python

I have the following code:
l = ['-1.2', '0.0', '1']
x = 100.0
for i in l:
if i < x:
x = i
print x
The code should find the lowest value in my list (-1.2) but instead when i print 'x' it finds the value is still 100.0
Where is my code going wrong?

To find the minimum value of a list, you might just as well use min:
x = min(float(s) for s in l) # min of a generator
Or, if you want the result as a string, rather than a float, use a key function:
x = min(l, key=float)

You aren't comparing integers, you're comparing strings. Strings compare lexicographically -- meaning character by character -- instead of (as you seem to want) by converting the value to a float. Make your list hold numbers (floats or integers, depending on what you want), or convert the strings to floats or integers in your loop, before you compare them.
You may also be interested in the min builtin function, which already does what your current loop does (without the converting, that is.)

It looks like you want to convert the list to a list of numbers
>>> foo = ['-1.2', '0.0', '1']
>>> bar = map(float, foo)
>>> bar
[-1.2, 0.0, 1.0]
>>> min(bar)
-1.2
or if it really is strings you want, that you want to use min's key argument
>>> foo = ['-1.2', '0.0', '1']
>>> min(foo, key=float)
'-1.2'

Python has a built in min function to help you with finding the smallest.
However, you need to convert your list items to numbers before you can find the lowest integer( what, isn't that float? )
min(float(i) for i in l)

l is a list of strings. When you put numbers between single quotes like that, you are creating strings, which are just a sequence of characters. To make your code work properly, you would have to do this:
l = [-1.2, 0.0, 1] # no quotation marks
x = 100.0
for i in l:
if i < x:
x = i
print x
If you must use a list of strings, you can try to let Python try to make a number out of each string. This is similar to Justin's answer, except it understands floating-point (decimal) numbers correctly.
l = ['-1.2', '0.0', '1']
x = 100.0
for i in l:
inum = float(i)
if inum < x:
x = inum
print x
I hope that this is code that you are writing to learn either Python or programming in general. If this is the case, great. However, if this is production code, consider using Python's built-in functions.
l = ['-1.2', '0.0', '1']
lnums = map(float, l) # turn strings to numbers
x = min(lnums) # find minimum value
print x

number_list = [99.5,1.2,-0.3]
number_list.sort()
print number_list[0]

Cast the variable to a float before doing the comparison:
if float(i) < float(x):
The problem is that you are comparing strings to floats, which will not work.

list1 = [10,-4,5,2,33,4,7,8,2,3,5,8,99,-34]
print(list1)
max_v=list1[0]
min_v=list1[0]
for x in list1:
if x>max_v:
max_v=x
print('X is {0} and max is {1}'.format(x,max_v))
for x in list1:
if x<min_v:
min_v=x
print('X is {0} and min is {1}'.format(x,min_v))
print('Max values is ' + str(max_v))
print('Min values is ' + str(min_v))

Or no float conversion at all by just specifying floats in the list.
l = [-1.2, 0.0, 1]
x = min(l)
or
l = min([-1.2, 0.0, 1])

You have to start somewhere the correct code should be:
The code to return the minimum value
l = [ '0.0', '1','-1.2']
x = l[0]
for i in l:
if i < x:
x = i
print x
But again it's good to use directly integers instead of using quotations ''
This way!
l = [ 0.0, 1,-1.2]
x = l[0]
for i in l:
if i < x:
x = i
print x

l = [-1.2, 0.0, 1]
x = 100.0
for i in l:
if i < x:
x = i
print (x)
This is the answer, i needed this for my homework, took your code, and i deleted the " " around the numbers, it then worked, i hope this helped

You have strings in the list and you are comparing them with the number 100.0.

'''Functions'''
import math
#functions
def min3(x1,x2,x3):
if x1<= x2 and x1<= x3:
return x1
elif x2<= x1 and x2<= x3:
return x2
elif x3<= x2 and x3<= x1:
return x3
print(min3(4, 7, 5))
print(min3(4, 5, 5))
print(min3(4, 4, 4))
print(min3(-2, -6, -100))
print(min3("Z", "B", "A"))

Related

Deleting list from a list of lists

I need to delete these lists inside of list that contains the / symbol.
List for example:
X = [['a/','$1'], ["c","d"]]
so X[0] should be deleted. The actual list are much longer and contains more instances of this condition.
I tried use something like:
print([l for l in X if l.count("/") <1])
But if I understand correctly because the / is attached to another symbol he is not counted.
Should I convert this list of lists to string, separate the / from another character, and then use the count function, or there is better solution?
One way to search "/" in each item in the sublists is to wrap a generator expression with any. Since you don't want sublists with "/" in it, the condition should be not any():
out = [lst for lst in X if not any('/' in x for x in lst)]
Output:
[['c', 'd']]
The call to filter() applies that lambda function to every list in X and filters out list with '/'.
result = list(filter(lambda l: not any('/' in s for s in l), X))
counter = 0
while counter < len(X):
removed = False
for i in X[counter]:
if '/' in i:
X.pop(counter)
removed = True
break
if not removed:
counter += 1
Given:
X = [['a/','$1'], ["c","d"]]
You can convert the sub lists to their repr string representations and detect the / in that string:
new_x=[sl for sl in X if not '/' in repr(sl)]
Or, you can use next:
new_x=[sl for sl in X if not next('/' in s for s in sl)]
Either:
>>> new_x
[['c', 'd']]

list of list multiplication with list

I want to multiply a list of list with a list using python 3 suppose that the list of list is of name L as follows:
L = [[45.909221207388235, 84.41069326628269], [80.6591435966521, 47.93257841035172]]
and the second list is:
S = [0.002, 0.001]
the multiplication should be: L[0][0]* S[0] and L[0][1]* S[0] then L[1][0]* S[1] and L[1][1]* S[1].
I tried the zip method :
[a*b for x,y in zip(S,L) for a,b in zip(x,y)]
But an error appears: zip argument 1 must support iteration.
the second trial was using map(lambda):
map(lambda x,y:x*y,L,S)
but the obtained results were wrong:
[9.181844241477647e-05, 0.00016882138653256538, 0.0001613182871933042, 9.586515682070343e-05]
the correct values are:
[0.09181844241477648, 0.1688213865325654, 0.0806591435966521, 0.047932578410351714]
You want to use zip, but not twice:
>>> L = [[45.909221207388235, 84.41069326628269], [80.6591435966521, 47.93257841035172]]
>>> S = [0.002, 0.001]
>>> [n*x for n, sub in zip(S, L) for x in sub]
[0.09181844241477648, 0.1688213865325654, 0.0806591435966521, 0.047932578410351714]
>>>
So, you want to pair up every number with every sublist, then multiply every number in the sublist by that main number.
Note, just in case you are using numpy (I don't think you are, and I don't think it would be reasonable to use numpy just for this), and S and L are numpy.ndarray objects, i.e.:
>>> S = np.array(S)
>>> L = np.array(L)
Then you probably just want:
>>> (S*L).ravel()
array([0.09181844, 0.08441069, 0.16131829, 0.04793258])
If I understand corresly you want to multiply each column in L by the corresponding value of S:
L = [[45.909221207388235, 84.41069326628269],
[80.6591435966521, 47.93257841035172]]
S = [0.002, 0.001]
R = [ [s*n for n in row] for s,row in zip(S,L) ]
output:
print(R)
[ [0.09181844241477648, 0.1688213865325654],
[0.0806591435966521, 0.047932578410351714]]
You should have given an example with a different number of rows than columns to make this clearer

Sorting Lists with numerals

If I have a list that all strings but with numerals :
a = ['0.01um', 'Control', '0.1um', '0.05um']
If I sort the list it looks like this
a.sort()
print(a)
['0.01um', '0.05um', '0.1um', 'Control']
How can I make it sort with so the strings starting with letters come before the strings starting with numbers, but the numbers are still ordered from smallest to biggest. For instance :
['Control', '0.01um', '0.05um', '0.1um']
Well, to get your strings starting with letters to collate before those starting with numerics sounds like you'd need to separate them, sort each, then append the one (sub)list to the the other.
To get "natural" sorting of strings containing numerics I'd look at natsort.
So the code might look something like:
#!python
# UNTESTED
import string
from natsort import natsorted
a = ['0.01um', 'Control', '0.1um', '0.05um']
astrs = [x for x in a if not x[0] in string.digits]
anums = [x for x in a if x[0] in string.digits]
results = natsorted(astrs) + natsorted(anums)
You can define a key function that “decorates” strings starting with letters with a value lower than strings starting with numbers. For example:
from itertools import takewhile
def get_numeric_prefix(str_):
return float(takewhile(char.isnumeric() or char == '.'))
def letters_before_numbers(str_):
if not str_:
return (3, str_)
elif str_[0].isalpha():
return (0, str_)
elif str_[0].isnumeric():
return (1, get_numeric_prefix(str_))
else:
return (2, str_)
a.sort(key=letters_before_numbers)
The initial not str_ case is necessary, because the conditions in the later cases access item 0, which would raise an IndexError if the string were empty. I've elected not to handle strings like '40.0.3um' (where there's a prefix that's all numbers and dots, but it's not a properly-formatted float)—those will cause the float() call to raise a ValueError. If you need those to be handled, you should probably grab a copy of natsort and use Jim's answer.
Tuples are compared lexicographically, so sort() looks at the number first—if it's lower, the original string will get sorted earlier in the list. This means that you can play with the numbers that are the first elements of the return values to get different kinds of strings to sort earlier or later than others. In this case, strings starting with letters will get sorted first, followed by strings starting with numbers (sorted by the numbers), then strings starting with neither, and finally empty strings.
Here is a trick involving python's tuple sorting semantics; strings which do not begin with a number will be sorted lexically before all numbers which will be sorted numerically:
In [1]: import re
In [2]: def parse_number(s):
try:
m = re.match(r'\d+(?:\.\d+)?', s)
return m and float(m.group(0))
except:
pass
In [3]: a = ['0.01um', 'Control', '0.1um', '0.05um']
In [4]: b = sorted((parse_number(i), i) for i in a)
In [5]: [i for _, i in b]
Out[5]: ['Control', '0.01um', '0.05um', '0.1um']
In code
a = ['0.01um', 'Control', '0.1um', '0.05um']
b = [x for x in a if x and x[0].isdigit()]
c = [x for x in a if x not in b]
d = sorted([(x, float(''.join([y for y in x if y.isdigit() or y == '.']))) for x in b], key=lambda x: x[1])
print sorted(c) + [k for k, v in d]

Find a string in a list of list in python

I have a nested list as below:
[['asgy200;f','ssll100',' time is: 10h:00m:12s','xxxxxxx','***','','asgy200;f','frl5100',' time is: 00h:00m:05s','ooo']]
'***' is my delimiter. I want to separate all of seconds in the list in python.
First of all with regular expression I want to separate the line that has time is: string but it doesn't work!
I don't know what should I do.
Thanks
import re
x=[['asgy200;f','ssll100','time is: 10h:00m:12s','xxxxxxx','***','','asgy200;f','frl5100','time is: 00h:00m:05s','ooo']]
s=str(x)
print re.findall(r"(?<=time is)\s*:\s*[^']*:(\d+)",s)
Output:['12', '05']
You can try this.
You can use a look-ahead regex (r'(?<=time is\:).*') :
>>> [i.group(0).split(':')[2] for i in [re.search(r'(?<=time is\:).*',i) for i in l[0]] if i is not None]
['12s', '05s']
and you can convert them to int :
>>> [int(j.replace('s','')) for j in sec]
[12, 5]
if you want the string of seconds don't convert them to int after replace :
>>> [j.replace('s','') for j in sec]
['12', '05']
You could use capturing groups also. It won't print the seconds if the seconds is exactly equal to 00
>>> lst = [['asgy200;f','ssll100','time is: 10h:00m:12s','xxxxxxx','***','','asgy200;f','frl5100','time is: 00h:00m:05s','ooo']]
>>> [i for i in re.findall(r'time\s+is:\s+\d{2}h:\d{2}m:(\d{2})', ' '.join(lst[0])) if int(i) != 00]
['12', '05']
>>> lst = [['asgy200;f','ssll100','time is: 10h:00m:00s','xxxxxxx','***','','asgy200;f','frl5100','time is: 00h:00m:05s','ooo']]
>>> [i for i in re.findall(r'time\s+is:\s+\d{2}h:\d{2}m:(\d{2})', ' '.join(lst[0])) if int(i) != 00]
['05']
Taking into account your last comment to your Q,
>>> x = [['asgy200;f','ssll100','time is: 10h:00m:12s','xxxxxxx','***','','asgy200;f','frl5100','time is: 00h:00m:05s','ooo']]
>>> print all([w[-3:-1]!='00' for r in x for w in r if w.startswith('time is: ')])
True
>>>
all and any are two useful builtins...
The thing operates like this, the slower loop is on the sublists (rows) of x, the fastest loop on the items (words)in each row, we pick up only the words that startswith a specific string, and our iterable is made of booleans where we have true if the 3rd last and 2nd last character of the picked word are different from'00'. Finally the all consumes the iterable and returns True if all the second fields are different from '00'.
HTH,
Addendum
Do we want to break out early?
all_secs_differ_from_0 = True
for row in x:
for word in row:
if word.startswith('time is: ') and word[-3:-1] == '00':
all_secs_differ_from_0 = False
break
if not all_secs_differ_from_0: break

Python - List.extend not returning expected value

I am trying to get a list all numbers divisible by three under 1000. I used this code:
y = []
for x in range(1000):
if not x % 3:
y.extend(str(x))
print y
However it simply returned a seemingly unordered list of integers under 10, repeated in no apparent order (If you would like to see this list just say, but it is very long and probably not useful). Does anyone know what I am doing wrong?
It is giving you the right numbers, it's just splitting them into individual characters.
Try list.append instead:
y.append(str(x))
Your meaning could be more explicit. It would make more sense to use x % 3 == 0 than not x % 3
This could also be summarised into a list comprehension:
y = [str(3 * i) for i in range(1000 / 3 + 1)]
Or, better yet (in my opinion), use map and range:
y = map(str, range(0, 1000, 3))
map applies the str function to every item in the list generated by range.
As pointed out in the comments, range creates a list of its own, the size of which depends on the length of the list. You can use xrange instead, to create an xrange object which can be used in the same way:
y = map(str, xrange(0, 1000, 3))
This avoids the creation of an intermediate list.
Your question is tagged python2.7 but note that in Python 3, the behaviour of range changes, so that it does what xrange does.
extend extends a list using another list. So when you try to extend a list using a string, it adds the digits of the number to the list.
>>> l = []
>>> l.extend(str(12))
>>> l
['1', '2']
The correct operator to use would be append, which appends a list to another list. But you should just do this instead:
y = [x for x in xrange(1000) if x%3 == 0] # use xrange in python2
Or just:
y = range(0, 1000, 3) # thanks to Sebastian for this
do:
y.append(str(x))
in place of
y.extend(str(x))
in case of extend, x considered to be list. For example, "123" considered as list with '1','2','3' as it's elements
Just another explanation and how to fix your snippet:
This is what list.extend says:
>>> help(list.extend)
Help on method_descriptor:
extend(...)
L.extend(iterable) -- extend list by appending elements from the iterable
>>>
In your case as string is iterable so it will iterable over your string and convert into a list of characters and extend to the original one.
So, we can fix your snippet using tuple or list instead of str:
Using single element tuple:
y = []
for x in range(1000):
if not x % 3:
y.extend((x,))
print y
Using single element list:
y = []
for x in range(1000):
if not x % 3:
y.extend([x])
print y

Categories