How to generate list of string with Random Characters using python3 - python-3.x

I tried with the below code but it seems not to give the intended output.
ran = ''.join(random.choice(string.ascii_uppercase+string.digits) for x in range(10))
So the above code gives '6U1S75' but I want output like
['6U1S75', '4Z4UKK', '9111K4',....]
Please help.

I thought this is elegant :
from string import digits, ascii_letters
from random import choices
def rand_list_of_strings(list_size, word_size, pool=ascii_letters + digits):
return ["".join(choices(pool, k=word_size)) for _ in range(list_size)]
I used ascii_letters instead of ascii_uppercase to have both upper and lower case values, you can edit it to your suiting.
Example use of the above function :
>>> rand_list_of_strings(4, 5)
['wBSbH', 'rJoH8', '9Gx4q', '8Epus']
>>> rand_list_of_strings(4, 10)
['UWyRglswlN', 'w0Yr7xlU5L', 'p0e6rghGMS', 'Z8zX2Vqyve']
>>>
The first argument is the list size, and the second argument is how large each consequent string should be, and the function invocation returns a list instance. Do not that this should not be used for cryptographic purposes.

Take a look at this.
list_size = 10
word_size = 4
ran = []
for i in range(list_size):
rans = ''
for j in range(word_size):
rans += random.choice(string.ascii_uppercase + string.digits)
ran.append(rans)
Though the above solution is clearer and should be preferred, if you absolutely want to do this with list comprehension...
list_size = 10
word_size = 4
ran = [
''.join([
random.choice(string.ascii_uppercase + string.digits)
for j in range(word_size)
])
for i in range(list_size)
]

Related

How to compute the average of a string of floats

temp = "75.1,77.7,83.2,82.5,81.0,79.5,85.7"
I am stuck in this assignment and unable to find a relevant answer to help.
I’ve used .split(",") and float()
and I am still stuck here.
temp = "75.1,77.7,83.2,82.5,81.0,79.5,85.7"
li = temp.split(",")
def avr(li):
av = 0
for i in li:
av += float(i)
return av/len(li)
print(avr(li))
You can use sum() to add the elements of a tuple of floats:
temp = "75.1,77.7,83.2,82.5,81.0,79.5,85.7"
def average (s_vals):
vals = tuple ( float(v) for v in s_vals.split(",") )
return sum(vals) / len(vals)
print (average(temp))
Admittedly similar to the answer by #emacsdrivesmenuts (GMTA).
However, opting to use the efficient map function which should scale nicely for larger strings. This approach removes the for loop and explicit float() conversion of each value, and passes these operations to the lower-level (highly optimised) C implementation.
For example:
def mean(s):
vals = tuple(map(float, s.split(',')))
return sum(vals) / len(vals)
Example use:
temp = '75.1,77.7,83.2,82.5,81.0,79.5,85.7'
mean(temp)
>>> 80.67142857142858

How can i optimise my code and make it readable?

The task is:
User enters a number, you take 1 number from the left, one from the right and sum it. Then you take the rest of this number and sum every digit in it. then you get two answers. You have to sort them from biggest to lowest and make them into a one solid number. I solved it, but i don't like how it looks like. i mean the task is pretty simple but my code looks like trash. Maybe i should use some more built-in functions and libraries. If so, could you please advise me some? Thank you
a = int(input())
b = [int(i) for i in str(a)]
closesum = 0
d = []
e = ""
farsum = b[0] + b[-1]
print(farsum)
b.pop(0)
b.pop(-1)
print(b)
for i in b:
closesum += i
print(closesum)
d.append(int(closesum))
d.append(int(farsum))
print(d)
for i in sorted(d, reverse = True):
e += str(i)
print(int(e))
input()
You can use reduce
from functools import reduce
a = [0,1,2,3,4,5,6,7,8,9]
print(reduce(lambda x, y: x + y, a))
# 45
and you can just pass in a shortened list instead of poping elements: b[1:-1]
The first two lines:
str_input = input() # input will always read strings
num_list = [int(i) for i in str_input]
the for loop at the end is useless and there is no need to sort only 2 elements. You can just use a simple if..else condition to print what you want.
You don't need a loop to sum a slice of a list. You can also use join to concatenate a list of strings without looping. This implementation converts to string before sorting (the result would be the same). You could convert to string after sorting using map(str,...)
farsum = b[0] + b[-1]
closesum = sum(b[1:-2])
"".join(sorted((str(farsum),str(closesum)),reverse=True))

How to count number of substrings in python, if substrings overlap?

The count() function returns the number of times a substring occurs in a string, but it fails in case of overlapping strings.
Let's say my input is:
^_^_^-_-
I want to find how many times ^_^ occurs in the string.
mystr=input()
happy=mystr.count('^_^')
sad=mystr.count('-_-')
print(happy)
print(sad)
Output is:
1
1
I am expecting:
2
1
How can I achieve the desired result?
New Version
You can solve this problem without writing any explicit loops using regex. As #abhijith-pk's answer cleverly suggests, you can search for the first character only, with the remainder being placed in a positive lookahead, which will allow you to make the match with overlaps:
def count_overlapping(string, pattern):
regex = '{}(?={})'.format(re.escape(pattern[:1]), re.escape(pattern[1:]))
# Consume iterator, get count with minimal memory usage
return sum(1 for _ in re.finditer(regex, string))
[IDEOne Link]
Using [:1] and [1:] for the indices allows the function to handle the empty string without special processing, while using [0] and [1:] for the indices would not.
Old Version
You can always write your own routine using the fact that str.find allows you to specify a starting index. This routine will not be very efficient, but it should work:
def count_overlapping(string, pattern):
count = 0
start = -1
while True:
start = string.find(pattern, start + 1)
if start < 0:
return count
count += 1
[IDEOne Link]
Usage
Both versions return identical results. A sample usage would be:
>>> mystr = '^_^_^-_-'
>>> count_overlapping(mystr, '^_^')
2
>>> count_overlapping(mystr, '-_-')
1
>>> count_overlapping(mystr, '')
9
>>> count_overlapping(mystr, 'x')
0
Notice that the empty string is found len(mystr) + 1 times. I consider this to be intuitively correct because it is effectively between and around every character.
you can use regex for a quick and dirty solution :
import re
mystr='^_^_^-_-'
print(len(re.findall('\^(?=_\^)',mystr)))
You need something like this
def count_substr(string,substr):
n=len(substr)
count=0
for i in range(len(string)-len(substr)+1):
if(string[i:i+len(substr)] == substr):
count+=1
return count
mystr=input()
print(count_substr(mystr,'121'))
Input: 12121990
Output: 2

Length of list returns length of list name

Import random
set_list_1 = ["one"]
set_list_2 = ["two"]
number = random.choice(range(1, 3))
chosen_list = "set_list_" + str(number)
print(len(chosen_list))
Returns 10 instead of 1
How do i get it to return the length of the list instead of the length of the lists name?
This is a bad idea. You should use lists.
Try this;
Import random
set_list = [[], ["one"], ["two"]]
number = random.choice(range(1, 3))
chosen_list = set_list[number]
print(len(chosen_list))
If you absolutely want to access variables dynamically;
Import random
set_list_1 = ["one"]
set_list_2 = ["two"]
number = random.choice(range(1, 3))
chosen_list = eval("set_list_" + str(number))
print(len(chosen_list))
To answer the question per se, chosen_list isn't the list, but a string. So then len() returns the length of a string, that is to say, the number of characters in it.
If you want to access the list instead by it's name :
As stated by the other answer and the comment, you could first use eval for this.
You can also use the locals() (or maybe globals() if your lists are in the global scope) (depending on your current scope) dictionnary to avoid eval. These functions return a dictionnary containing everything you can access in the global (well the module scope to be accurate) / local scope.
import random
set_list_1 = ["one"]
set_list_2 = ["two"]
number = random.choice(range(1, 3))
chosen_list = locals()["set_list_" + str(number)]
print(len(chosen_list))
It's probably faster and safer than eval.
Or, you can register your lists in a dict, mapping the variable name to the ̀list. For instance, you can do something like this :
import random
registry = {}
registry["set_list_1"] = ["one"]
registry["set_list_2"] = ["two"]
number = random.choice(range(1, 3))
chosen_list = registry["set_list_" + str(number)]
print(len(chosen_list))
This is without a doubt even faster than using locals(), and is actually a common pattern in python. Here is a classic example of this, involving metaclasses.
Also, you can do this if you don't actually need the variables names for any other reason :
import random
registry = []
registry.append(["one"])
registry.append(["two"])
chosen_list = random.choice(registry)
print(len(chosen_list))

Repeat string to certain length

What is an efficient way to repeat a string to a certain length? Eg: repeat('abc', 7) -> 'abcabca'
Here is my current code:
def repeat(string, length):
cur, old = 1, string
while len(string) < length:
string += old[cur-1]
cur = (cur+1)%len(old)
return string
Is there a better (more pythonic) way to do this? Maybe using list comprehension?
Jason Scheirer's answer is correct but could use some more exposition.
First off, to repeat a string an integer number of times, you can use overloaded multiplication:
>>> 'abc' * 7
'abcabcabcabcabcabcabc'
So, to repeat a string until it's at least as long as the length you want, you calculate the appropriate number of repeats and put it on the right-hand side of that multiplication operator:
def repeat_to_at_least_length(s, wanted):
return s * (wanted//len(s) + 1)
>>> repeat_to_at_least_length('abc', 7)
'abcabcabc'
Then, you can trim it to the exact length you want with an array slice:
def repeat_to_length(s, wanted):
return (s * (wanted//len(s) + 1))[:wanted]
>>> repeat_to_length('abc', 7)
'abcabca'
Alternatively, as suggested in pillmod's answer that probably nobody scrolls down far enough to notice anymore, you can use divmod to compute the number of full repetitions needed, and the number of extra characters, all at once:
def pillmod_repeat_to_length(s, wanted):
a, b = divmod(wanted, len(s))
return s * a + s[:b]
Which is better? Let's benchmark it:
>>> import timeit
>>> timeit.repeat('scheirer_repeat_to_length("abcdefg", 129)', globals=globals())
[0.3964178159367293, 0.32557755894958973, 0.32851039397064596]
>>> timeit.repeat('pillmod_repeat_to_length("abcdefg", 129)', globals=globals())
[0.5276265419088304, 0.46511475392617285, 0.46291469305288047]
So, pillmod's version is something like 40% slower, which is too bad, since personally I think it's much more readable. There are several possible reasons for this, starting with its compiling to about 40% more bytecode instructions.
Note: these examples use the new-ish // operator for truncating integer division. This is often called a Python 3 feature, but according to PEP 238, it was introduced all the way back in Python 2.2. You only have to use it in Python 3 (or in modules that have from __future__ import division) but you can use it regardless.
def repeat_to_length(string_to_expand, length):
return (string_to_expand * ((length/len(string_to_expand))+1))[:length]
For python3:
def repeat_to_length(string_to_expand, length):
return (string_to_expand * (int(length/len(string_to_expand))+1))[:length]
This is pretty pythonic:
newstring = 'abc'*5
print newstring[0:6]
def rep(s, m):
a, b = divmod(m, len(s))
return s * a + s[:b]
from itertools import cycle, islice
def srepeat(string, n):
return ''.join(islice(cycle(string), n))
Perhaps not the most efficient solution, but certainly short & simple:
def repstr(string, length):
return (string * length)[0:length]
repstr("foobar", 14)
Gives "foobarfoobarfo". One thing about this version is that if length < len(string) then the output string will be truncated. For example:
repstr("foobar", 3)
Gives "foo".
Edit: actually to my surprise, this is faster than the currently accepted solution (the 'repeat_to_length' function), at least on short strings:
from timeit import Timer
t1 = Timer("repstr('foofoo', 30)", 'from __main__ import repstr')
t2 = Timer("repeat_to_length('foofoo', 30)", 'from __main__ import repeat_to_length')
t1.timeit() # gives ~0.35 secs
t2.timeit() # gives ~0.43 secs
Presumably if the string was long, or length was very high (that is, if the wastefulness of the string * length part was high) then it would perform poorly. And in fact we can modify the above to verify this:
from timeit import Timer
t1 = Timer("repstr('foofoo' * 10, 3000)", 'from __main__ import repstr')
t2 = Timer("repeat_to_length('foofoo' * 10, 3000)", 'from __main__ import repeat_to_length')
t1.timeit() # gives ~18.85 secs
t2.timeit() # gives ~1.13 secs
How about string * (length / len(string)) + string[0:(length % len(string))]
i use this:
def extend_string(s, l):
return (s*l)[:l]
Not that there haven't been enough answers to this question, but there is a repeat function; just need to make a list of and then join the output:
from itertools import repeat
def rep(s,n):
''.join(list(repeat(s,n))
Yay recursion!
def trunc(s,l):
if l > 0:
return s[:l] + trunc(s, l - len(s))
return ''
Won't scale forever, but it's fine for smaller strings. And it's pretty.
I admit I just read the Little Schemer and I like recursion right now.
This is one way to do it using a list comprehension, though it's increasingly wasteful as the length of the rpt string increases.
def repeat(rpt, length):
return ''.join([rpt for x in range(0, (len(rpt) % length))])[:length]
Another FP aproach:
def repeat_string(string_to_repeat, repetitions):
return ''.join([ string_to_repeat for n in range(repetitions)])
def extended_string (word, length) :
extra_long_word = word * (length//len(word) + 1)
required_string = extra_long_word[:length]
return required_string
print(extended_string("abc", 7))
c = s.count('a')
div=n//len(s)
if n%len(s)==0:
c= c*div
else:
m = n%len(s)
c = c*div+s[:m].count('a')
print(c)
Currently print(f"{'abc'*7}") generates:
abcabcabcabcabcabcabc

Resources