How To Generate A List Of Possible Combination From A Set Dictionary - python-3.x

I'm a beginner coder, I have the code below
def PossibleNum(List):
DefaultSymbol = '%'
NumDict = ["0","1","2","3","4","5","6","7","8","9"]
FinishList = []
for Item in List:
for i in range(len(NumDict)):
_item = Item.replace(DefaultSymbol,NumDict[i])
FinishList.append(_item)
return FinishList
List = ["AAAA%%","BBB%%%","CC%%C%"]
print (PossibleNum(List))
I'm trying to get every possible combination from NumDict by Replacing each of "%" into every possible NumDict
Wanted Output : [AAAA00,AAAA01,AAAA02,AAAA03....,AAAA99]
Current Output : [AAAA11,AAAA22,AAAA33,AAAA,44,AAAA55,AAAA66]

You can use str.replace with count parameter set to 1. To obtain the combinations, I used str.format method.
For example:
lst = ["AAAA%%","BBB%%%","CC%%C%"]
output = []
for i in lst:
n = i.count('%')
backup = i
for v in range(10**n):
i = backup
for ch in '{:0{n}}'.format(v, n=n):
i = i.replace('%', ch, 1)
output.append(i)
# pretty print:
from pprint import pprint
pprint(output)
Prints:
['AAAA00',
'AAAA01',
'AAAA02',
'AAAA03',
...all the way to:
'CC99C5',
'CC99C6',
'CC99C7',
'CC99C8',
'CC99C9']

An option using itertools.product to get all the possible inserts:
import itertools
l = ["AAAA%%","BBB%%%","CC%%C%"]
DefaultSymbol = '%'
NumDict = ["0","1","2","3","4","5","6","7","8","9"]
out = []
for s in l:
n = s.count(DefaultSymbol)
prod = itertools.product(NumDict, repeat=n)
for p in prod:
tmp = s
for i in p:
tmp = tmp.replace(DefaultSymbol, i, 1)
out.append(tmp)
Pretty straight forward; for each input list element get the number of replacements (count of '%'), calculate all possible elements to insert using itertools.product, then iterate over all these elements (for p in prod) and do the replacements, one at a time (for i in p, with replace count set to 1).

Related

Don't understand why I am getting list index out of range here

I wrote this to simulate studying for a test
#number of questions
qList = [] * q
#question numbers
for i in range(len(qList)):
qList[i] = i + 1
#questions studied
sList = [] * s
for i in range (0,s):
x = randint(0,len(qList))
sList[i] = qList[x]
#questions passed
pList = []
for i in range(len(sList)):
if i in sList and i in qList:
pList.apppend(i)
the line sList[i] = qList[x] gives me an index out of range error. I haven't used lists in a while and I can't figure out what is wrong here.
I am trying to get the output here as three lists
a list of questions
the questions that have been studied
the questions passed
randint includes both boundaries:
Return a random integer N such that a <= N <= b. Alias for randrange(a, b+1).
Change invocation to:
x = randint(0, len(qList) - 1)
# or
x = randrange(0, len(qList))
Also you are instantiating empty arrays, you need to pass some element so it can be repeated (or better use list comprehensions):
qList = [1] * q
sList = [1] * s

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 remove tuple from zip?

so i have a bunch of numbers i've tupled but am having difficulty remove an item from the zipped list.
so far i've tried .remove on the list but that gave me an error.
is there an easy way of doing this?
this is my current code:
Example data:
QueenRowColumn: 3,3
TheComparisonQueen: 7,3
def CheckQueenPathDown(self, QueenRowColumn, TheComparisonQueen):
row = []
column = []
CurrentLocation = QueenRowColumn
#MoveLocation = TheComparisonQueen
a = QueenRowColumn[0]
b = QueenRowColumn[1]
for i in range (-7,0):
row.append(CurrentLocation[1] - i)
column.append(a)
Down = zip(row,column)
#Down.remove(TheComparisonQueen)
return Down
if i, for example were to remove "TheComparisonQueen" from the list of tuples, how would i do it?
If you just looking to drop TheComparisonQueen from iterator of tuples you can return values that are not equal to TheComparisonQueen using a list comprehension or a generator expression.
# List Comprehension
Down = [(i,j) for i,j in zip(row,column) if (i,j) != TheComparisonQueen]
# Generator Expression
Down = ((i,j) for i,j in zip(row,column) if (i,j) != TheComparisonQueen)

Writing sequences into separate list or array

I'm trying to extracts these sequences into separate lists or arrays in Python from a file.
My data looks like:
>gene_FST
AGTGGGTAATG--TGATG...GAAATTTG
>gene_FPY
AGT-GG..ATGAAT---AAATGAAAT--G
I would like to have
seq1 = [AGTGGGTAATG--TGATG...GAAATTTG]
seq2 = [AGT-GG..ATGAAT---AAATGAAAT--G]
My plan is to later compare the contents of the list
I would appreciate any advise
So far, here's what I have done, that
f = open (r"C:\Users\Olukayode\Desktop\my_file.txt", 'r') #first r - before the normal string it converts normal string to raw string
def parse_fasta(lines):
seq = []
seq1 = []
seq2 = []
head = []
data = ''
for line in lines:
if line.startswith('>'):
if data:
seq.append(data)
data = ''
head.append(line[1:])
else:
data+= line.rstrip()
seq.append(data)
return seq
h = parse_fasta(f)
print(h)
print(h[0])
print(h[1])
gives:
['AGTGGGTAATG--TGATG...GAAATTTG', 'AGT-GG..ATGAAT---AAATGAAAT--G']
AGTGGGTAATG--TGATG...GAAATTTG
AGT-GG..ATGAAT---AAATGAAAT--G
I think I just figured it out, I can pass each string the list containing both sequences into a separate list, if possible though
If you want to get the exact results you were looking for in your original question, i.e.
seq1 = [AGTGGGTAATG--TGATG...GAAATTTG]
seq2 = [AGT-GG..ATGAAT---AAATGAAAT--G]
you can do it in a variety of ways. Instead of changing anything you already have though, you can just convert your data into a dictionary and print the dictionary items.
your code block...
h = parse_fasta(f)
sDict = {}
for i in range(len(h)):
sDict["seq"+str(i+1)] = [h[i]]
for seq, data in sDict.items():
print(seq, "=", data)

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))

Resources