rstrip only working for first dictionary entry - python

so im using rstrip to get rid of new line identifier at end of end of dictionary entries
Here's dictionary I am working with:
{'100': ['Smith', 'James', '66', '150\n'], '101': ['Jones', 'Linda', '62', '124\n'], '102': ['Davis', 'David', '68', '180\n'], '103': ['Miller', 'Sandra', '65', '90\n'], '104': ['Taylor', 'Paul', '72', '150\n']}
notice \n at the end of each
So to get rid of this I create a list of only the keys. then use of for loop to ammend each entry.
keys = [k for k in dictionary]
for key in keys:
dictionary[key][3] = dictionary[key][3].rstrip('\n')
However when I do this the output gets rid of the first \n only for key 100, but the rest stay. Here's what the new dictionary looks like:
{'100': ['Smith', 'James', '66', '150'], '101': ['Jones', 'Linda', '62', '124\n'], '102': ['Davis', 'David', '68', '180\n'], '103': ['Miller', 'Sandra', '65', '90\n'], '104': ['Taylor', 'Paul', '72', '150\n']}
Process finished with exit code 0
the first entry is fixed perfectly but the rest stay the same. I cant figure out why the for loop doesnt run through all the keys, but only the first one :(

Using dict.items() will make your life easy while iterating through it. But here since you only need to update values, you can use dict.values() to iterate over values
Also use index -1 to get the last element in the list
dictionary = {'100': ['Smith', 'James', '66', '150\n'], '101': ['Jones', 'Linda', '62', '124\n'], '102': ['Davis', 'David', '68', '180\n'], '103': ['Miller', 'Sandra', '65', '90\n'], '104': ['Taylor', 'Paul', '72', '150\n']}
for value in dictionary.values():
value[-1] = value[-1].rstrip('\n')
print(dictionary)
#{'100': ['Smith', 'James', '66', '150'],
#'101': ['Jones', 'Linda', '62', '124'],
#'102': ['Davis', 'David', '68', '180'],
#'103': ['Miller', 'Sandra', '65', '90'],
#'104': ['Taylor', 'Paul', '72', '150']}

While we're all suggesting different ways to do this, note that you don't actually need to use the keys at all. The values are lists, so they're mutable. Thus, here's another approach:
dictionary = {'100': ['Smith', 'James', '66', '150\n'], '101': ['Jones', 'Linda', '62', '124\n'], '102': ['Davis', 'David', '68', '180\n'], '103': ['Miller', 'Sandra', '65', '90\n'], '104': ['Taylor', 'Paul', '72', '150\n']}
for value in dictionary.values():
value[-1] = value[-1].rstrip("\n")
dictionary
# {'100': ['Smith', 'James', '66', '150'],
# '101': ['Jones', 'Linda', '62', '124'],
# '102': ['Davis', 'David', '68', '180'],
# '103': ['Miller', 'Sandra', '65', '90'],
# '104': ['Taylor', 'Paul', '72', '150']}

Related

How to sort default dict with list values in python

I have a defaultdict with list as
defaultdict(<class 'list'>, {'SOL200122': ['125', '135', '145', '170', '120', '130', '140', '150', '160']}
I want it to be sorted like
defaultdict(<class 'list'>, {'SOL200122': ['120', '125', '130', '135', '140', '145', '150', '160', '170']}
Have tried
sorted(myDict.items(), key=lambda k_v: (k_v[1][2]), reverse=True)
But not working
Use list.sort with key=int (thanks #Metapod, #deceze et al):
for v in d.values():
v.sort(key=int)
If you want a one-liner (which makes no sense in this case because for-loop is very nice), a monstrosity like this one could be one I guess:
dict(zip(d.keys(), map(lambda x: sorted(x, key=int), d.values())))
Output:
{'SOL200122': ['120', '125', '130', '135', '140', '145', '150', '160', '170']}
try this:
for v in d.values():
v.sort(key=int)
output:
{'SOL200122': ['120', '125', '130', '135', '140', '145', '150', '160', '170']}

Python list concatenation logic

I was trying to concatenate two lists, which are 'Names' and 'Ages'.
But I wanted to do that with appending their index of [i+1] each time to another list.
So instead of ['John', '17', 'Mike', '21'], My goal was that each pair has a different index, and were a list element.Like that --> [['John', '17'], ['Mike', '21']]
(Note: I know I can do that with zip() function, this is for practice)
So I ended up with that code -->
names = ['Ana', 'John', 'Bob', 'Mike', 'July']
ages = ['17', '22', '33', '8', '76']
a = []
b = []
for i in range(len(names)):
a.append(names[i])
a.append(ages[i])
b.append([] + a)
a.clear()
print(b)
Output --> [['Ana', '17'], ['John', '22'], ['Bob', '33'], ['Mike', '8'], ['July', '76']]
So as you can see I managed to do that, but the weird thing is that line b.append([] + a). I got what I want accidently, when I type b.append(a) it returns empty b list.
But by following the path in the attached code, I'm accomplishing what I'm trying to do. Can anybody explain why this is working ? I could not catch it.
Thanks in advance.
Adding prints in the code shows that b gets 'cleared' after the loop, and it was not storing the correct information inside the loop. It is essentially copies of the same a:
names = ['Ana', 'John', 'Bob', 'Mike', 'July']
ages = ['17', '22', '33', '8', '76']
a = []
b = []
for i in range(len(names)):
a.append(names[i])
a.append(ages[i])
print(a)
b.append(a)
print(b)
a.clear()
print(b)
['Ana', '17']
[['Ana', '17']]
['John', '22']
[['John', '22'], ['John', '22']]
['Bob', '33']
[['Bob', '33'], ['Bob', '33'], ['Bob', '33']]
['Mike', '8']
[['Mike', '8'], ['Mike', '8'], ['Mike', '8'], ['Mike', '8']]
['July', '76']
[['July', '76'], ['July', '76'], ['July', '76'], ['July', '76'], ['July', '76']]
[[], [], [], [], []]
This is because lists are mutable in python. When you clear it, the data b is pointing to gets removed as well. When you do []+a, you are creating a new list which is not a reference to a any more. By changing the code this way you can get what you want:
names = ['Ana', 'John', 'Bob', 'Mike', 'July']
ages = ['17', '22', '33', '8', '76']
b = []
for i in range(len(names)):
a = []
a.append(names[i])
a.append(ages[i])
b.append(a)
print(b)
To help you understand what I mean by mutable, see the following example:
a = ['some data']
b = [a]
print(b)
a.clear()
print(b)
[['some data']]
[[]]
And this is why a+[] works:
a = ['some data']
b = [a+[]]
print(b)
a.clear()
print(b)
[['some data']]
[['some data']]
if both the list have same no of elements then you can use zip() function.
Note: The zip() function will only iterate till the smallest list passed.
list1=[]
for x,y in zip(names,ages):
list1.append([x,y])
print(list1)
Following is my solution using a list comprehension.
names = ['Ana', 'John', 'Bob', 'Mike', 'July']
ages = ['17', '22', '33', '8', '76']
new_list = [ [names[i], ages[i]] for i in range(len(names))]
print(new_list)
names = ['Ana', 'John', 'Bob', 'Mike', 'July']
ages = ['17', '22', '33', '8', '76']
a = []
b = []
for i in range(len(names)):
a.append(names[i])
a.append(ages[i])
b.append([]+a)
a.clear()
print(b)
According to your code b.append([]+a)
it is concatenation every time with array.if you checked with print statement like this
for i in range(len(names)):
a.append(names[i])
a.append(ages[i])
print("=>",a)
then show you output is
=> ['Ana', '17']
=> ['John', '22']
=> ['Bob', '33']
=> ['Mike', '8']
=> ['July', '76']
so that when you add b.append([]+a)
we understand more clearly for now
b = []
when we try
b.append([]+a)
it's mean above array concatenate the many arrays into one array .
I think you solve your problem easily when you using
zip() for iteration.
myList=[]
for a,b in zip(names,ages):
list.append([a,b])
print(myList)
output:
[['Ana', '17'], ['John', '22'], ['Bob', '33'], ['Mike', '8'], ['July', '76']]
I would use zip within a list comprehension:
names = ['Ana', 'John', 'Bob', 'Mike', 'July']
ages = ['17', '22', '33', '8', '76']
b = [[name,age] for name, age in zip(names,ages)]
you can use zip and list to write this in a single line of code:
result = list(zip(names, ages))

Merge list for 2d list, its separating correctly but when it comes back all together it is wrong,

Here is my code, the code is usual merge sort but with my print statements showing each step, the only issue I have is when it comes back all together there are duplicate values and stuff of that matter
def mergeSort(list):
if len(list) > 1:
mid = len(list) // 2
left = list[:mid]
right = list[mid:]
print("left:\n"+str(left).replace("],","]\n"))
print("right:\n"+str(right).replace("],","]\n"))
print("")
#recursion
mergeSort(left)
mergeSort(right)
i = j = k = 0
while i < len(left) and j < len(right):
if left[i][0] < right[j][0]:
list[k].append(left[i][0])
i += 1
else:
list[k].append(right[j][0])
j += 1
k += 1
while i < len(left):
list[k].append(left[i][0])
i += 1
k += 1
while j < len(right):
list[k].append(right[j][0])
j += 1
k += 1
This is the output
left:
[['21', 'John', 'S.', '$100.00']
['20', 'Mark', 'Z.', '$123.00']
['18', 'Susan', 'K.', '$0.00']]
right:
[['25', 'Paul', 'A.', '$0.00']
['44', 'Elvis', 'P.', '$4,000.00']
['8', 'Lucas', 'L.', '$5.00']]
left:
[['21', 'John', 'S.', '$100.00']]
right:
[['20', 'Mark', 'Z.', '$123.00']
['18', 'Susan', 'K.', '$0.00']]
left:
[['20', 'Mark', 'Z.', '$123.00']]
right:
[['18', 'Susan', 'K.', '$0.00']]
left:
[['25', 'Paul', 'A.', '$0.00']]
right:
[['44', 'Elvis', 'P.', '$4,000.00']
['8', 'Lucas', 'L.', '$5.00']]
left:
[['44', 'Elvis', 'P.', '$4,000.00']]
right:
[['8', 'Lucas', 'L.', '$5.00']]
[['21', 'John', 'S.', '$100.00', '20', '21']
['20', 'Mark', 'Z.', '$123.00', '18', '18', '20']
['18', 'Susan', 'K.', '$0.00', '20', '21', '18']
['25', 'Paul', 'A.', '$0.00', '25', '25']
['44', 'Elvis', 'P.', '$4,000.00', '44', '44', '44']
['8', 'Lucas', 'L.', '$5.00', '8', '8', '8']]
I was able to merge sort if it was just an array with the same "first column values" and thats how I know it is separating correctly. I just cannot see where I went wrong with my function, maybe im just blind.
I found three mistakes in your code.
Never ever call a variable list in python
Find another name for the argument of your function. list is already the name of the class that handles everything related to lists in python. Giving this name to another object leads to unforeseen trouble. Instead, call your variable l, or ll, or myList, or whatever other name you can think of.
You are comparing strings instead of numbers
By default, strings are compared according to lexicographical order. Thus, '2' > '18', because '2' begins with the character '2' whereas '18' begins with the character '1'. This is most likely not what you want. You can either modify your list before sorting to replace those strings with numbers; or you can replace your test if left[i][0] < right[j][0]: with if int(left[i][0]) < int(right[j][0]):
Your merge function is appending the wrong things at the wrong places
Let me illustrate the effect of the line list[k].append(left[i][0]) using python's interactive interpreter:
>>> left = [['21', 'John', 'S.', '$100.00'],['20', 'Mark', 'Z.', '$123.00'],['18', 'Susan', 'K.', '$0.00']]
>>> myList = [['21', 'John', 'S.', '$100.00'],['20', 'Mark', 'Z.', '$123.00'],['18', 'Susan', 'K.', '$0.00'],['25', 'Paul', 'A.', '$0.00'],['44', 'Elvis', 'P.', '$4,000.00'],['8', 'Lucas', 'L.', '$5.00']]
>>> i = 0
>>> k = 0
>>> myList[k].append(left[i][0])
>>> myList
[['21', 'John', 'S.', '$100.00', '21'],
['20', 'Mark', 'Z.', '$123.00'],
['18', 'Susan', 'K.', '$0.00'],
['25', 'Paul', 'A.', '$0.00'],
['44', 'Elvis', 'P.', '$4,000.00'],
['8', 'Lucas', 'L.', '$5.00']]
What happened? myList[k] is an element of myList: since myList is a list of lists, in this case it's the list corresponding to John. left[i] is the first element of left; since left is a list of lists, in this case it's the list corresponding to John. Finally, left[i][0] is the first element of John's list, which is the string '21'. So you are appending the element '21' to the list ['21', 'John', 'S.', '$100.00'], and this results in John's list in myList becoming ['21', 'John', 'S.', '$100.00', '21'].
How to fix it? Simply write myList[k] = left[i] instead. This will replace the kth element of myList with the ith element of left, which is what you want.

Value overrided after round played, visible when printed out

My code:
users = []
users.append({"name" : "",
"numerics" : [],
"score" : 0 })
users[0]["name"] = input("Your name plz: ")
def getNumbers():
for i in range(len(users)):
numbers = input("Assign 8 different numbers (separate each with a comma ','): ")
userNumbers = numbers.split(",")
return userNumbers
users[0]["numerics"] = getNumbers()
scores = []
scores.append(users[:])
print(scores)
users[0]["numerics"] = getNumbers()
scores.append(users[:])
print(scores)
Running example:
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> users = []
>>> users.append({"name" : "",
"numerics" : [],
"score" : 0 })
>>> users[0]["name"] = input("Your name plz: ")
Your name plz: Gladiator
>>> def getNumbers():
for i in range(len(users)):
numbers = input("Assign 8 different numbers (separate each with a comma ','): ")
userNumbers = numbers.split(",")
return userNumbers
>>> users[0]["numerics"] = getNumbers()
Assign 8 different numbers (separate each with a comma ','): 99,23,55,11,19,100,1000,89
>>> scores = []
>>> scores.append(users[:])
>>> print(scores)
[[{'numerics': ['99', '23', '55', '11', '19', '100', '1000', '89'], 'name': 'Gladiator', 'score': 0}]]
>>> users[0]["numerics"] = getNumbers()
Assign 8 different numbers (separate each with a comma ','): 100,56,77,32,99,22,45,2
>>> scores.append(users[:])
>>> print(scores)
[[{'numerics': ['100', '56', '77', '32', '99', '22', '45', '2'], 'name': 'Gladiator', 'score': 0}], [{'numerics': ['100', '56', '77', '32', '99', '22', '45', '2'], 'name': 'Gladiator', 'score': 0}]]
>>>
I want to be able to for each new round in the game, make changes to the user numerics and score, and append it to the score list and then print that out. However, it seems like my current way is just overriding the numerics and the score. But mostly the numerics part.
This doesn't seem to work at all: users[0]["score"].append(getNumbers())
Or should I simply clear the values in the list, e.g. score and numerics for each new round for the player.
Round 1:
Player: Gladiator
Numerics: ['99', '23', '55', '11', '19', '100', '1000', '89']
Round 2:
Player: Gladiator
Numerics: ['100', '56', '77', '32', '99', '22', '45', '2']
But the print out shows:
[[{'numerics': ['100', '56', '77', '32', '99', '22', '45', '2'],
'name': 'Gladiator', 'score': 0}],
[{'numerics': ['100', '56', '77', '32', '99', '22', '45', '2'],
'name': 'Gladiator', 'score': 0}]]
EDIT: I tried resetting the list of numerics:
users[0]['numerics'] = []
TypeError: list indices must be integers or slices, not tuple
Test ran the code example by #Sarathsp
Your name plz: Gladiator
Assign 8 different numbers (separate each with a comma ','): 99,100,1000,4,66,77,11,9
[[{'name': 'Gladiator', 'numerics': ['99', '100', '1000', '4', '66', '77', '11', '9'], 'score': 0}]]
Assign 8 different numbers (separate each with a comma ','): 100,33,44,55,0,1,9,2
[[{'name': 'Gladiator', 'numerics': ['99', '100', '1000', '4', '66', '77', '11', '9'], 'score': 0}], [{'name': 'Gladiator', 'numerics': ['100', '33', '44', '55', '0', '1', '9', '2'], 'score': 0}]]
Assignment statements in Python do not copy objects, they create bindings between a target and an object. You have to use deep copy to copy the users list
there is a module copy
you may use it as
copy.deepcopy(users)
Here is how your program look like
import copy
users = []
users.append({"name" : "",
"numerics" : [],
"score" : 0 })
users[0]["name"] = input("Your name plz: ")
def getNumbers():
for i in range(len(users)):
numbers = input("Assign 8 different numbers (separate each with a comma ','): ")
userNumbers = numbers.split(",")
return userNumbers
users[0]["numerics"] = getNumbers()
scores = []
scores.append(copy.deepcopy(users))
print(scores)
users[0]["numerics"] = getNumbers()
scores.append(copy.deepcopy(users))
print(scores)

How to parse/format a string of tuples?

I jus wrote a grade calculating program and am down to the last few lines ... I have this string of tuples :
"('Jetson Elroy', '45', '88', '88', '70', 0.7253846153846155, 'C', 'Not Passible', 0.9385714285714284, 0.6528571428571427, 0.367142857142857), ('Joe Kunzler', '99', '88', '77', '55', 0.7699999999999999, 'C', 'Not Passible', 0.8557142857142858, 0.5700000000000001, 0.28428571428571436), ('Harris Jones', '77', '99', '47', '77', 0.7115384615384616, 'C', 'Not Passible', 0.9642857142857143, 0.6785714285714286, 0.39285714285714285)"
I'd like to make it so each student and their scores are printed into my text file line by line, like :
'Jetson', '45', '88', '88', '70', 0.7253846153846155, 'C', 'Not Passible', 0.9385714285714284, 0.6528571428571427, 0.367142857142857
'Joe', '99', '88', '77', '55', 0.7699999999999999, 'C', 'Not Passible', 0.8557142857142858, 0.5700000000000001, 0.28428571428571436
'Harris Jones', '77', '99', '47', '77', 0.7115384615384616, 'C', 'Not Passible', 0.9642857142857143, 0.6785714285714286, 0.39285714285714285
I tried to do :
m=open('GradeAnalysis.txt', 'r+')
m.write (print i for i in ourlist)
m.close()
But I realize you have to have a string if you want to use m.write(). Then I transferred my list into the string of tuples like I have above. Any pythonic suggestions are appreciated.
join() can be a simple solution:
m.write('\n'.join(i for i in ourstring))
Edit: Since ourstring is not a list of strings but a string, you can use a regular expression to get the strings that represent the tuples
import re
ourstring = "('Jetson Elroy', '45', '88', '88', '70', 0.7253846153846155, 'C', 'Not Passible', 0.9385714285714284, 0.6528571428571427, 0.367142857142857), ('Joe Kunzler', '99', '88', '77', '55', 0.7699999999999999, 'C', 'Not Passible', 0.8557142857142858, 0.5700000000000001, 0.28428571428571436), ('Harris Jones', '77', '99', '47', '77', 0.7115384615384616, 'C', 'Not Passible', 0.9642857142857143, 0.6785714285714286, 0.39285714285714285)"
tuples = re.findall(r'\((.+?)\)', ourstring) # (.+?) to perform a non-greedy match - important!
m.write ('\n'.join(t for t in tuples))
Use either str.join() or the csv module to write your data.
Using ','.join(str(i) for i in ourlist) creates a comma-separated string to write to the file, but since this is really CSV data, the csv module is perhaps better suited.
import csv
with open('GradeAnalysis.txt', 'rb') as out:
writer = csv.writer(out)
for row in list_of_sequences:
out.writerow(row)
where list_of_sequences is then a list containing other lists or tuples; for example:
list_of_sequences = [(1, 2, 3), ('foo', 'bar', 'baz')]

Categories

Resources