With a string of ints:
myStr = '3848202160702781329 2256714569201620911 1074847147244043342'
How could one do an average of the string ints while keeping the string data type ?
Here what I thought in pseudo code:
sum = 0
res = eval(myStr[i] + ' + sum')
avg = res/len(myStr)
If You want to get the average of those integers in that string this is one way:
myStr = '3848202160702781329 2256714569201620911 1074847147244043342'
print(sum(lst := [int(x) for x in myStr.split()]) / len(lst))
basically You get the sum of a list of those integers that are in that string and also use that operator (forgot the name) to assign that list to a variable while simultaneously return that value, then just divide the sum by the length of that list
EDIT1, 2, 3: just remembered, it is called walrus operator, some info can be found here (video by Lex Fridman) and here, as well as other places, also it requires Python version of 3.8 or higher
EDITn: the reason behind the use of the walrus operator is that it allowed to not repeat code in this one-liner, otherwise the list comprehension would have been used twice (in sum and in len) which could affect performance for very large lists (and I wanted it to be a one-liner)
You could split the string, and map it to integers then find the sum of the list. Lastly divide the sum by the length of the split list.
myStr = '3848202160702781329 2256714569201620911 1074847147244043342'
print(sum(map(int,myStr.split()))/len(myStr.split()))
output
2.3932546257161487e+18
Since (the absolute valid) other answers show one-liner solutions I'd like to show the different steps. This might help to understand what's going on.
>>> myStr = '3848202160702781329 2256714569201620911 1074847147244043342'
>>> data = myStr.split()
>>> data
['3848202160702781329', '2256714569201620911', '1074847147244043342']
>>> data = list(map(int, data))
>>> data
[3848202160702781329, 2256714569201620911, 1074847147244043342]
>>> sum(data)
7179763877148445582
>>> sum(data) / len(data)
2.3932546257161487e+18
Related
For example, is it possible to convert the input
x = 10hr
into something like
y = 10
z = hr
I considering slicing, but the individual parts of the string will never be of a fixed length -- for example, the base string could also be something like 365d or 9minutes.
I'm aware of split() and re.match which can separate items into a list/group based on delimitation. But I'm curious what the shortest way to split a string containing a string and an integer into two separate variables is, without having to reassign the elements of the list.
You could use list comprehension and join it as a string
x='10hr'
digits="".join([i for i in x if not i.isalpha()])
letters="".join([i for i in x if i.isalpha()])
You don't need some fancy function or regex for your use case
x = '10hr'
i=0
while x[i].isdigit():
i+=1
The solution assumes that the string is going to be in format you have mentioned: 10hr, 365d, 9minutes, etc..
Above loop will get you the first index value i for the string part
>>i
2
>>x[:i]
'10'
>>x[i:]
'hr'
I have a list with floats, for example
numbers = [1000.45,1002.98,1005.099,1007.987]
I want to create a new list containing the deltas of the value in numbers - i.e. I want the difference between numbers[0],[numbers[1] to be the first value in a new list. So the first number in my new list should be 2.53, the second should be 2.119, and so forth.
I tried list comprehension
newnumbers= [i[-1] - i[-2] for i in numbers]
but it gives a TypeError
TypeError: 'float' object is not subscriptable
I tried converting the list to integers, but then it gives the same type of error.
How can I create my desired list?
It's easy with Pandas, use diff():
import pandas as pd
pd.Series(numbers).diff()
0 NaN
1 2.530
2 2.119
3 2.888
dtype: float64
You've got the right idea, but just haven't quite got the syntax right. You should use:
newnumbers = [(numbers[i] - numbers[i-1]) for i in range(1, len(numbers))]
In your version you're trying to index a number, but you need to index your list instead.
newnumbers = []
for i in range(1,len(numbers)-1):
newnumbers.append(numbers[i]-numbers[i-1])
for i in numbers i is equal to 1000.45 in the first loop, then 1002.98 etc. So i[-1] = 1000.45[-1] which means nothing, you cannot subscriptable a float
numbers = [1000.45,1002.98,1005.099,1007.987]
newnumbers= [numbers[i+1]-numbers[i] for i in range(len(numbers)-1)]
print(newnumbers)
#[2.5299999999999727, 2.119000000000028, 2.88799999999992]
If you want 2 decimal points
newnumbers= [float("%0.2f"%(numbers[i+1]-numbers[i])) for i in range(len(numbers)-1)]
#[2.53, 2.12, 2.89]
Note how you access your elements directly, instead of using list indices;
The correct way to do the latter in Python would be
for index in range(len(numbers)):
What you are using is essentially the numbers themselves. Also, note that you would have to exclude the first index of your list, since you only want the differences (otherwise, the first call would look at the last index again, according to Python's behavior of calling mylist[-1]), which is why you can restrict your range to range(1,len(numbers)). In the form of a list comprehension, it would now work like this:
newnumbers = [numbers[i] - numbers[i-1] for i in range(1,len(numbers))]
Here is a method that doesn't require importing any modules:
numbers = [1000.45,1002.98,1005.099,1007.987]
sliced = numbers[1:]
answer = list(map((lambda x,y: y - x),sliced,numbers))
This gives:
[-2.5299999999999727, -2.119000000000028, -2.88799999999992]
You can then do:
final_answer = [round(x,2) for x in answer]
which gives:
[-2.53, -2.12, -2.89]
>>> numbers = [1000.45,1002.98,1005.099,1007.987]
>>> [round((y-x),2) for x,y in zip(numbers, numbers[1:])]
[2.53, 2.12, 2.89]
I am trying to find the sum of all numbers in a list but every time I try I get an error that it cannot convert the string to float. Here is what I have so far.
loop = True
float('elec_used')
while (loop):
totalelec = sum('elec_used')
print (totalelec)
loop = False
You need none of your code above. The while loop is unnecessary and it looks like its just exiting the loop in one iteration i.e. its not used correctly. If you're simply summing all the values in the list:
sum([float(i) for i in elec_used])
If this produces errors, please post your elec_used list. It probably contains string values or blank spaces.
'elec_used' is of type string of characters. You can not convert characters to the float. I am not sure why you thought you could do it. However you can convert the numeric string to float by typecasting it. For example:
>>> number_string = '123.5'
>>> float(number_string)
123.5
Now coming to your second part, for calculating the sum of number. Let say your are having the string of multiple numbers. Firstly .split() the list, type-cast each item to float and then calculate the sum(). For example:
>>> number_string = '123.5 345.7 789.4'
>>> splitted_num_string = number_string.split()
>>> number_list = [float(num) for num in splitted_num_string]
>>> sum(number_list)
1258.6
Which could be written in one line using list comprehension as:
>>> sum(float(item) for item in number_string.split())
1258.6
OR, using map() as:
>>> sum(map(float, number_string.split()))
1258.6
I would like to get some integers from a string (the 3rd one). Preferable without using regex.
I saw a lot of stuff.
my string:
xp = '93% (9774/10500)'
So i would like the code to return a list with integers from a string. So the desired output would be: [93, 9774, 10500]
Some stuff like this doesn't work:
>>> new = [int(s) for s in xp.split() if s.isdigit()]
>>> print new
[]
>>> int(filter(str.isdigit, xp))
93977410500
Since the problem is that you have to split on different chars, you can first replace everything that's not a digit by a space then split, a one-liner would be :
xp = '93% (9774/10500)'
''.join([ x if x.isdigit() else ' ' for x in xp ]).split() # ['93', '9774', '10500']
Using regex (sorry!) to split the string by a non-digit, then filter on digits (can have empty fields) and convert to int.
import re
xp = '93% (9774/10500)'
print([int(x) for x in filter(str.isdigit,re.split("\D+",xp))])
result:
[93, 9774, 10500]
Since this is Py2, using str, it looks like you don't need to consider the full Unicode range; since you're doing this more than once, you can slightly improve on polku's answer using str.translate:
# Create a translation table once, up front, that replaces non-digits with
import string
nondigits = ''.join(c for c in map(chr, range(256)) if not c.isdigit())
nondigit_to_space_table = string.maketrans(nondigits, ' ' * len(nondigits))
# Then, when you need to extract integers use the table to efficiently translate
# at C layer in a single function call:
xp = '93% (9774/10500)'
intstrs = xp.translate(nondigit_to_space_table).split() # ['93', '9774', 10500]
myints = map(int, intstrs) # Wrap in `list` constructor on Py3
Performance-wise, for the test string on my 64 bit Linux 2.7 build, using translate takes about 374 nanoseconds to run, vs. 2.76 microseconds for the listcomp and join solution; the listcomp+join takes >7x longer. For larger strings (where the fixed overhead is trivial compared to the actual work), the listcomp+join solution takes closer to 20x longer.
Main advantage to polku's solution is that it requires no changes on Py3 (on which it should seamlessly support non-ASCII strings), where str.translate builds the translation table a different way there (str.translate) and it would be impractical to make a translation table that handled all non-digits in the whole Unicode space.
Since the format is fixed, you can use consecutive split().
It's not very pretty, or general, but sometimes the direct and "stupid" solution is not so bad:
a, b = xp.split("%")
x = int(a)
y = int(b.split("/")[0].strip()[1:])
z = int(b.split("/")[1].strip()[:-1])
print(x, y, z) # prints "93 9774 10500"
Edit: Clarified that the poster specifically said that his format is fixed. This solution is not very pretty, but it does what it's supposed to.
I have a sequence of events. 1's are good, 0s are bad.
Looking for the most Pythonic way of finding the maximum, minimum and average length of 1 sequences.
For example:
seq ="001000000000001101001000000000111100001000000011000010000010001100000110011001000010000010101100001110110001000000100100000011000000001000001000101001000000001000010000010011011000100001000011100000001100010001010100100011011000001000000100010110001101100000000100001000001"
One approach would be splitting your string on zeros, dropping empty strings, mapping by length, and sorting:
wins = sorted(map(len, filter(None, seq.split("0"))))
After that your shortest streak would be at index zero, the longest one would be at the last index (accessible with -1) and the average would be easily computable by applying sum and dividing by length converted to float:
print(wins[-1]) # 4
print(wins[0]) # 1
print(sum(wins) / float(len(wins))) # 1.4339622641509433
Demo.
You can do this using list comprehensions and the len function to get the list of wins length but before that you need to split your string on zeros using the split method.
seq = "001000000000001101001000000000111100001000000011000010000010001100000110011001000010000010101100001110110001000000100100000011000000001000001000101001000000001000010000010011011000100001000011100000001100010001010100100011011000001000000100010110001101100000000100001000001"
>>> wins_len = [len(el) for el in seq.split('0') if el]
>>> max(wins_len)
4
>>> min(wins_len)
1
To compute the average use sum and len
>>> sum(wins_len) / len(wins_len)
1.4339622641509433
or the mean function from the statistics module new in Python 3.4
>>> from statistics import mean
>>> mean(wins_len)
1.4339622641509433
Not very Pythonic, but I would catch all the ones with regex like this :
(1{1,})
Demo
and then proceed like this,
>>> s=re.findall(r'(1{1,})',a)
>>> length_of_ones=[len(i) for i in s]
>>> max(length_of_ones)
4
>>> min(length_of_ones)
1
>>> sum(length_of_ones)*1.0/len(length_of_ones)
1.4339622641509433
where a is your given string.