Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am absolutly new in python and in programing, I made this bifid cipher, I'd like to hear opinions about how to improve and make it look more elegant, thanks in advance.
I been taking courses in Codecademy and Udacity, and I've learn quite a lot.
import itertools
#Genera coodernadas-Generate Coordinates
coordinates = [[x,y] for x in range(1,6) for y in range(1,6)]
#Genera alfabeto-Generate Alphabet
alfa = []
for i in range(97,123):
alfa.append(chr (i))
alfa.remove("i")
#Genera diccionario de coordenadas y alfabeto - Generate dictionary and coordinates alphabet
alfacor = {}
alfacor = dict(zip(alfa,coordinates))
#Leer Txt - Read txt
document = open("Z:\\R\\Desktop\\BIFIDO\\easy.txt")
contenido = document.read()
print (contenido)
document.close()
#Encripta fase1 - Get's coordinates of txt
encripta = []
for e in contenido:
encripta.append(alfacor[e])
#Unir lista encripta - Merge content of encropita in a new list
merged = list(itertools.chain.from_iterable(encripta))
#Divido lista merge en partes iguales - Divide meged list to get new coordinates
B = merged[:len(merged)/2]
C = merged[len(merged)/2:]
#Unir B y C - Zip B and C to get a new list of coordinates
zipped = zip(B,C)
#Make a new list from zipped to convert from tuple to list
final_list = [list(elem) for elem in zipped]
#Convert contect of alfacor to tuples
inv_alfacor = {}
for letter, coordinate in alfacor.iteritems():
inv_alfacor[tuple(coordinate)] = letter
#Substitude coordinates of final_list from elements of inv_alfacor
encripta_f = []
for element in final_list:
element = tuple(element)
if element in inv_alfacor:
encripta_f.append(inv_alfacor[element])
print "Tu palabra ",encripta_f
Other than perhaps using comprehensions and avoid the unnecessary tuple -> list -> tuple conversions, reduce the number of intermediate variables then it might be slightly easier to read. I would also consider making it a function that you pass in a string and an encrypted string is returned:
from itertools import chain, product
def bifid(data):
# Leave coordinates as tuples and appropriate use of itertools.product
coordinates = product(range(1, 6), repeat=2)
# Using comprehensions and generators to construct the list/dicts vs loops
# Leave alfa as a generator as it is only used once
alfa = (chr(i) for i in range(97, 123) if chr(i) != 'i')
alfacor = dict(zip(alfa, coordinates))
inv_alfacor = {coordinate: letter for letter, coordinate in alfacor.iteritems()}
encripta = (alfacor[e] for e in data)
merged = list(chain(*encripta))
final_list = zip(merged[:len(merged)//2], merged[len(merged)//2:])
return "".join(inv_alfacor[e] for e in final_list if e in inv_alfacor)
# Use with it closes automatically and handles exceptions correctly
with open("Z:\\R\\Desktop\\BIFIDO\\easy.txt") as document:
data = document.read()]
print "Tu palabra: {}".format(bifid(data))
Output:
"helloworld" -> Tu palabra: kmcyobnalt
Use with statement
You can read more in python docs or in this article Understanding Python's "with" statement
Suggested modification:
#Leer Txt - Read txt
with open("Z:\\R\\Desktop\\BIFIDO\\easy.txt", "r") as document:
contenido = document.read()
print (contenido)
Use list comprehensions
More info in Python docs or in the tutorial Python Tutorial: List Comprehensions
Suggested modification:
#Genera alfabeto-Generate Alphabet
alfa = [chr(i) for i in xrange(97, 123) if chr(i) != "i"]
(Note, please, this change also includes a condition in the list comprehension - example at SO question)
And also:
#Encripta fase1 - Get's coordinates of txt
encripta = [alfacor[e] for e in contenido]
Use generators
The first thing you can start with is following. When you write a list comprehension and you know you are going to iterate only one item of the list a time, change the brackets from [] to (). This is really simplified but it is the first thing you can do. Another related tip, when you use range(x) just like for i in range(x), use xrange(x) instead. xrange is a generator version of range.
More info in Python Wiki
Suggested change:
#Make a new list from zipped to convert from tuple to list
final_list = (list(elem) for elem in zipped)
Printing
In this case, using the print you used is fine, but have a look at string formatting.
More in Python docs and a few examples here.
Possible change:
print "Tu palabra {}".format(encripta_f)
You don't need to initialize all the variables.
You don't need to initialize alfacor dictionary when you assign a completely new value to the variable. However, you need to initialize variable when you work with it later.
Thus there is a difference between
# no need for initialization
alfacor = {}
# because you assign a new value here to the variable `alfacor`
alfacor = dict(zip(alfa,coordinates))
and this:
# you need to initialize this
alfacor = {}
# because you are working with the empty dictionary here
alfacor["my_key"] = "my_value"
Related
How can I convert the following dictionary which contains an array within an array: to an array easily so I can access for example array[0]
{'New Beton': [`'C:\\User\\New map\\Test1.jpg',`'C:\\User\\New map\\Test2.jpg', 'C:\\User\\New map\\Test3.jpg']}
Which I need to convert to
New Beton = ["C:\\User\\New map\\Test1.jpg", "C:\\User\\New map\\Test2.jpg", "C:\\User\\New map\\Test3.jpg"]
Just access it directly.
you_dict['New Beton'][0]
And make sure your variable names don't have whitespace. I think except 'Rockstar' no language allows that.
Do you want to convert dictionary into a nested list? Then, something like this will work.
def convert(d):
l = []
for k, v in d.items():
l.append(v)
return l
d = {'foo':['bar', 'baz']}
l = convert(d)
print(l[0])
but there are better ways to get that value without creating a list. it'd ve great if you could share more details about what you want to do so that i can give you specific examples.
This question already has answers here:
How to modify list entries during for loop?
(10 answers)
Closed 11 months ago.
I run a query and want to make a list from this query. I only need those select items, which I got, but I can't get rid of "," in lst.
I tried replace but it didn't work.
query = """
select
supplier_no_and_name,
accepted,
rejected,
pending,
tdc
from edl_current.supplier_warranty_cost_recovery_warranty_alteryx
where claim_date > "2021-01-01"
"""
lst = query.split()
lst = lst[1-len(lst):len(lst)-13]
for i in range(len(lst)):
lst[i].replace(',',"")
print(lst)
The output is following:
['supplier_no_and_name,', 'accepted,', 'rejected,', 'pending,', 'tdc']
replace method has a return value which is string meaning it doesn't update the original value itself. So, you need to assign with a new value using same variable or anything.
lst[i] = lst[i].replace(',',"")
str.rstrip() and list comprehension would be simpler.
# for i in range(len(lst)):
# lst[i]=lst[i].replace(',',"")
l = [ x.rstrip(',') for x in lst ]
lst = l[:l.index('tdc')+1] # for making same output.
Try this:-
query = """
select
supplier_no_and_name,
accepted,
rejected,
pending,
tdc
from edl_current.supplier_warranty_cost_recovery_warranty_alteryx
where claim_date > "2021-01-01"
"""
lst = query.split()
lst = lst[1-len(lst):len(lst)-13]
for i in range(len(lst)):
lst[i] = lst[i].replace(',', "")
d = ' '.join(lst)
print(d)
Things you should follow next time you ask questions on stack overflow.
Add the expected output in proper format.
Show the things that you've tried in the post.
Frame your question properly and always add error message if found any.
Most importantly search the question on stack overflow before posting it
85 % of time you'll get the answers without posting.
Your current solution is super brittle in that you need to know in advance the exact number of words in your SQL statement. I think you want to try to be a little more flexible and pick out the SELECT and FROM clauses:
query = """
select
supplier_no_and_name,
accepted,
rejected,
pending,
tdc
from edl_current.supplier_warranty_cost_recovery_warranty_alteryx
where claim_date > "2021-01-01"
"""
query_parts = [
p.strip(",")
for p
in query.replace("\n", " ").split()
if p
]
select_index = query_parts.index("select")
from_index = query_parts.index("from")
lst = query_parts[select_index+1 : from_index]
print(lst)
This should give you:
['supplier_no_and_name', 'accepted', 'rejected', 'pending', 'tdc']
Without being sensitive to the number of words or columns.
Since strings are immutable, their replace() method returns a new string with the modifications as opposed to doing them "in place". This means you have to explicitly replace the values in the list.
for i, value in enumerate(lst):
lst[i] = value.replace(',', '')
I want to make this into a proper list by adding commas in-between the values in brackets.
[119033] [656516, 34751, 2180, 656495, 66509032, 441462, 24801909, 134694146] [3220] [68313] [104735] [110685] [6432223] [565394] [519872] [] [5320377] [10855848] [11789573] [] [13745740] [101293645] [] [5464156, 94060] [] [] [] [] [6654] [2537]
I want the output to look like this
[119033], [656516, 34751, 2180, 656495, 66509032, 441462, 24801909, 134694146], [3220],[68313], [104735], [110685], [6432223], [565394], [519872], [], [5320377], [10855848], [11789573], [], [13745740], [101293645], [], [5464156, 94060], [], [], [], [], [6654], [2537]
And if possible I would also like to remove the empty brackets.
If the original data is a string, you can just use str.replace() to insert the commas.
input_str = '[119033] [656516, 34751, 2180, 656495, 66509032, 441462, 24801909, 134694146] [3220] [68313] [104735] [110685] [6432223] [565394] [519872] [] [5320377] [10855848] [11789573] [] [13745740] [101293645] [] [5464156, 94060] [] [] [] [] [6654] [2537]'
output_str = input_str.replace('] [', '], [')
print(output_str)
Note that this is still not the format of a proper list, because that needs [] around the whole thing. You can then convert that to a list using ast.literal_eval().
import ast
proper_list = ast.literal_eval('[' + output_str + ']');
print(proper_list);
You can get rid of the empty brackets with a list comprehension.
no_empty = [el for el in proper_list if el]
If this data was generated a function that returns a list that is repeatedly called (which, for the sake of simplicity, I will just call list_generator()), rather than being a string formatted this way, then you could simply do something like this:
new_list = []
for i in range(1,10):
new_list.append(list_generator(i))
That is, for each call of list_generator in the iteration of your set, you simply append it to an empty list. If you want to discard empty lists, then just add a check for empty lists prior to appending it.
new_list = []
for i in range(1,10):
list_item = list_generator(i)
if list_item:
new_list.append(list_item)
Of course, you'd replace the for for i in range(1,10) iteration with whatever iteration you're actually using, as well as replacing list_generator(i) with whatever function and parameters are actually being used to generate these values.
I have considered that the given in input is entirely a string. Which means
input ="[119033] [656516, 34751, 2180, 656495, 66509032, 441462, 24801909, 134694146] [3220] [68313] [104735] [110685] [6432223] [565394] [519872] [] [5320377] [10855848] [11789573] [] [13745740] [101293645] [] [5464156, 94060] [] [] [] [] [6654] [2537]"
Then your problem is purely on string manipulation. I want to notify that I did not want to use Regular expressions in this scenario and I just went on coding using for and if-else. Using Regular expressions might make your code more compact. Nevertheless, I started off by stripping away unwanted white spaces and commas at this point and stored the content in 'temp' by using the following code -
temp=[(i.strip("[").strip("]").split()) for i in string.replace(", ",",").split(" ")]
print(temp)
The print(temp) statement is used for debugging & understanding purposes which you are at liberty to remove as seen fit. Since you did not want any blank lists, I dealt with that query in the following code -
RemovedBlankLists=[]
[[RemovedBlankLists.append(j.split(",")) for j in i] for i in temp]
print(RemovedBlankLists)
Again the print(RemovedBlankLists) statement is used for debugging & understanding purposes which you may remove as seen fit. The above gets rid of blank lists and splits the lists at , which will be useful in the next step. The final part of the code is as follows -
y=[]
for i in RemovedBlankLists:
if len(i) < 1:
[y.append(int(j)) for j in i]
else:
temp = [int(j) for j in i]
y.append(temp)
print(y)
The last print(y) statement shall produce your desired output. Happy Coding !
Let me know if my assumption is wrong and If I have to consider the input as something else. I would love to code for the alternative too.
Maybe try this:
for x in list_of_data:
if x == '[]':
pass
else:
print(x)
That should at least get rid of the empty brackets.
I don't know what to do, this doesn't look like a normal datatype for Python...
Let's say I have such a list:
['word_4_0_w_7',
'word_4_0_w_6',
'word_3_0_w_10',
'word_3_0_w_2']
and I want to sort them according to number that comes after "word" and according to number after "w".
It will look like this:
['word_3_0_w_2',
'word_3_0_w_10',
'word_4_0_w_6',
'word_4_0_w_7']
What comes in mind is to create a bunch of list and according to index after "word" stuff them with sorted strings according "w", and then merge them.
Is in Python more clever way to do it?
Use Python's key functionality, in conjunction with other answers:
def mykey(value):
ls = value.split("_")
return int(ls[1]), int(ls[-1])
newlist = sorted(firstlist, key=mykey)
## or, if you want it in place:
firstlist.sort(key=mykey)
Python will be more efficient with key vs cmp.
You can provide a function to the sort() method of list objects:
l = ['word_4_0_w_7',
'word_4_0_w_6',
'word_3_0_w_10',
'word_3_0_w_2']
def my_key_func(x):
xx = x.split("_")
return (int(xx[1]), int(xx[-1]))
l.sort(key=my_key_func)
Output:
print l
['word_3_0_w_2', 'word_3_0_w_10', 'word_4_0_w_6', 'word_4_0_w_7']
edit: Changed code according to comment by #dwanderson ; more info on this can be found here.
You can use a function to extract the relevant parts of your string and then use those parts to sort:
a = ['word_4_0_w_7', 'word_4_0_w_6', 'word_3_0_w_10', 'word_3_0_w_2']
def sort_func(x):
parts = x.split('_');
sort_key = parts[1]+parts[2]+"%02d"%int(parts[4])
return sort_key
a_sorted = sorted(a,key=sort_func)
The expression "%02d" %int(x.split('_')[4]) is used to add a leading zero in front of second number otherwise 10 will sort before 2. You may have to do the same with the number extracted by x.split('_')[2].
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
I am a beginner in python. I want to Create new List object in python.
My Code:
recordList=[]
mappedDictionay={}
sectionGroupName= None
for record in recordCols:
item = record
print item
if not sectionGroupName == record[0]:
sectionGroupName = record[0]
del recordList[0:] # Here I want to create new list object for recordList
recordList.append(item)
mappedDictionay[sectionGroupName] = recordList
else:
recordList.append(tempItem)
It's not that easy to understand your question, especially since your code lost its formatting, but you can create new list objects quite easily. The following assigns a new list object to the variable recordList:
recordList = list()
You could also use
recordList = []
[] and list() are equivalent in this case.
Python is garbage-collected. Just do
recordList = []
and you'll have a new empty list.
Don't use del. Period. It's an "advanced" thing.
from collections import defaultdict
mappedDictionay= defaultdict( list ) # mappedDictionary is a poor name
sectionGroupName= None
for record in recordCols:
mappedDictionay[record[0]].append( record )
You can use list() or simply [] to create a new list.
However, I think what you are trying to achieve can be solved simply by using grouby:
from itertools import groupby
mappedIterator = groupby(recordCols, lambda x: x[0])
or
from itertools import groupby
from operator import itemgetter
mappedIterator = groupby(recordCols, itemgetter(0))
if you prefer.
The groupBy function will return an iterator rather than a dictionary, where each item is of the form (category, sub-iterator-over-items-in-that-category).
If you really want to convert it into a dictionary like you have it in your code, you can run the following afterwards:
mappedDictionary = dict(( (x[0], list(x[1])) for x in mappedIterator ))
You want to create a new list?
It's easy: for eg, you wanna make a list of days, write the following:
new_list=['mon','tue','wed','thurs','fri',sat','sun']
Here the name of the list is new_list and it contains the name of different week days.
Note: never forget use [ ] brackets to make a list, using ( ) will create a tuple, a very different object and { } will create a dictionary object which will raise a error instead.
It's easy to create a new list!
If you want it empty, then just define it like this:
NameOfList = []
or:
NameOfList = list()