Python dictionaries formatting - python-3.x

Python3 I have a dictionary with alphabet count, shown below
a 24873
b 5293
c 7301
d 15567
e 38088
f 6499
g 7109
h 20360
i 20283
j 751
k 3207
l 12780
m 7686
n 21510
o 24944
p 5275
q 191
r 16751
s 18831
t 30897
u 9624
v 2551
w 8390
x 439
y 7139
z 161
and i want a function to print it as
e 38088 i 20283 w 8390 b 5293 q 191
t 30897 s 18831 m 7686 p 5275 z 161
o 24944 r 16751 c 7301 k 3207
a 24873 d 15567 y 7139 v 2551
n 21510 l 12780 g 7109 j 751
h 20360 u 9624 f 6499 x 439
I tried taking keys and values into lists but is randomly changing as a dictionary is not ordered. Thanks in advance for the help.

You can use dict.items() to get the key-value pairs as a list of tuples. Then sort this list by the value.
For example:
d = {
'a': 24873,
'b': 5293,
'c': 7301,
'd': 15567
}
for k, v in sorted(d.items(), key=lambda x: x[1], reverse=True):
print("{} {}".format(k, v))
#a 24873
#d 15567
#c 7301
#b 5293
We sort the key-value pair tuples using a custom key, lambda x: x[1], which gets the element at index 1 in the tuple. In this case, that element is the count.
Also, we specify reverse=True to indicate that we want the sorted list to be in descending order.

from itertools import zip_longest
def printCol(l, numCols=5):
"""Takes a sorted list 'l' and displays it in 'numCols', the first items
get into col1, the next in col2 etc."""
# partition the sorted list
steps = len(l)//numCols+1
part = [l[i:i+steps] for i in range(0,len(l),steps)]
# transpose it into tuple-rows
zpart = zip_longest(*part,())
for row in zpart:
for t in row:
if t: # zip_longest produces () - do not display them
print(t[1],t[0], end = " ")
print("") # newline
You have to prepare your data a bit:
d ={"a":24873,"b":5293 ,"c":7301 ,"d":15567 ,"e":38088 ,
"f":6499 ,"g":7109 ,"h":20360 ,"i":20283 ,"j":751 ,
"k":3207 ,"l":12780 ,"m":7686 ,"n":21510 ,"o":24944 ,
"p":5275 ,"q":191 ,"r":16751 ,"s":18831 ,"t":30897 ,"u":9624 ,
"v":2551 ,"w":8390 ,"x":439 ,"y":7139 ,"z":161 }
# list comp: create tuples of (count, character) so sort will sort it by count
l = [ (am,ch) for ch,am in d.items()] # create tuples, amount first for sorting
l.sort(reverse=True) # sort descending by count, if equal, then by char
printCol(l,5) # print it
Output:
e 38088 i 20283 w 8390 b 5293 q 191
t 30897 s 18831 m 7686 p 5275 z 161
o 24944 r 16751 c 7301 k 3207
a 24873 d 15567 y 7139 v 2551
n 21510 l 12780 g 7109 j 751
h 20360 u 9624 f 6499 x 439

This is the solution I figured out with just traditional loops and not many in built functions. ThankYou
<pre>
def printTable(value):
no_of_rows = len(value)//5+1
i = 0
while(i < no_of_rows):
for j in range(0, len(value), no_of_rows):
if i+j < len(value):
print(str(value[i+j][0]).rjust(3),
str(value[i+j][1]).rjust(5), end=" ")
print("")
i += 1
d ={"a":24873, "b":5293, "c":7301, "d":15567, "e":38088,
"f":6499, "g":7109, "h":20360, "i":20283, "j":751,
"k":3207, "l":12780, "m":7686, "n":21510, "o":24944,
"p":5275, "q":191, "r":16751, "s":18831, "t":30897,
"u":9624, "v":2551, "w":8390, "x":439, "y":7139,
"z":161}
dic_to_sortlist = sorted(alph_freq.items(), key=operator.itemgetter(1),
reverse=True)
printTable(dic_to_sortlist)
</pre>

Related

How to delete an index from the first list that is also in the second list

For example, I have 2 lists:
list1 = [6,6,6,6,6,6,6]
list2 = [0,2,4]
If there are the same indexes in the list1 and list2, I need to remove these indexes from the list1, because I should sum the unique indexes from the list1, for example:
a = [1,2,3,4,5]
b = [0,2,4]
x = [a.index(i) for i in a]
y = [b.index(j) for j in b]
for idx in y:
if idx in x:
x.remove(idx)
print(sum(x))
printed is >> 7
I tried this but did not work if there are the same values in list1
a = [6,6,6,6,6,6,6]
b = [0,2,4]
x = [a.index(i) for i in a]
y = [b.index(j) for j in b]
for idx in y:
if idx in x:
x.remove(idx)
printed is >> 0
Indexes and values are different. There will never be the same index twice in one list. You get their index by their value, however index(value) function gives you the first index which matches your value. Have a look at:
a, b, x = [1,2,3,4,5,6,7], [1,2,3], 0
c, d = len(a), len(b)
if d < c:
d, c = len(a), len(b)
for i in range(c, d):
x += i
print(x)
Your question is not very clear, so here are two answers:
If you want to sum the elements from the first list that do not appear in the second list, here is a way to do it:
a = [1,2,3,4,5]
b = [0,2,4]
# We create a set in order to have O(1) operations to check if an element is in b
b_set = set(b)
# We sum on the values of a that are not in b
res = sum(x for x in a if x not in b_set)
print(res)
>>> 9
If you want to sum the elements of the first list that do not have their rank/index in the second list, a way to do that could be:
a = [1,2,3,4,5]
b = [0,2,4]
# We create a set in order to have O(1) operations to check if an element is in b
b_set = set(b)
# We sum on the values of a that don't have their rank/index in b
res = sum(x for (i, x) in enumerate(a) if i not in b_set)
print(res)
>>> 6

Conpressing repeated loops

I wrote the following code for a HackerRank problem involving repeated FOR loops with very similar syntax:
x, y = map(int, input().split())
inp = []
for _ in range(x):
inp.append(list(map(int, input().split())))
#I get the rest of the input as a nested list.
while len(inp) < 7:
inp.append([1, 0])
#Adding dummy values in the list
list = []
for a in inp[0][1:inp[0][0]+1]:
for b in inp[1][1:inp[1][0]+1]:
for c in inp[2][1:inp[2][0] + 1]:
for d in inp[3][1:inp[3][0] + 1]:
for e in inp[4][1:inp[4][0] + 1]:
for f in inp[5][1:inp[5][0] + 1]:
for g in inp[6][1:inp[6][0] + 1]:
list.append((a ** 2 + b ** 2 + c ** 2 + d ** 2 + e ** 2 + f ** 2 + g ** 2) % y)
#Given function
print(max(list))
I wonder if there's any way to do this in one go.
PS: I'm an absolute beginner in programming.
Use itertools.product can simplify the loops a little bits:
import itertools as it
K, M = map(int, input().strip().split())
# reading the K lines and appending lists to 'L'
L = []
for i in range(K):
lst = list(map(int, input().strip().split()))
L.append(lst[1:])
# Looping through Cartesian product
MAX = -1
for i in it.product(*L):
MAX = max(sum(map(lambda x: x**2, i))% M, MAX)
print(MAX)

Start counting indexes from 1 instead of 0 of a list

I created a program to get the the max value of a list and the position of its occurrences (list starting at indexing with 1 not 0) but I can't manage to find any useful solutions.
The input is always a string of numbers divided by zero.
This is my code:
inp = list(map(int,input().split()))
m = max(inp)
count = inp.count(m)
print(m)
def maxelements(seq): # #SilentGhost
return [i for i, j in enumerate(seq) if j == m]
print(maxelements(inp))
I expect to output the maximum value and then all the positions of its occurrences. (also is it possible to do without brackets as in the example below?)
Input: 4 56 43 45 2 56 8
Output: 56
2 6
If you want to shift index values, you could just do
return [i + 1 for i, j in enumerate(seq) if j == m]
more generally any transformation of i or j!
def f(i, j):
# do whatever you want, and return something
return i + 1
return [f(i, j) for i, j in enumerate(seq) if j == m]
Without brackets, as a string:
return " ".join(str(i + 1) for i, j in enumerate(seq) if j==m)
Specifiy start=1 with enumerate():
>>> l = [4, 56, 43, 45, 2, 56, 8]
>>> max_num = max(l)
>>> [i for i, e in enumerate(l, start=1) if e == max_num]
[2, 6]
By default enumerate() uses start=0, because indices start at 0.

Get length of range in Python List Comprehension

I wonder if it is possible to get the length of the range in a list comprehension in python 3 in order to set up a conditional as such? this code doesn't work
b = [x**2 for x in range(10) if x % 2 == 0 and x > len/2]
>>> n = 10
>>> b = [x**2 for x in range(n) if x % 2 == 0 and x > n/2]
>>> b
[36, 64]

String concatenation queries

I have a list of characters, say x in number, denoted by b[1], b[2], b[3] ... b[x]. After x,
b[x+1] is the concatenation of b[1],b[2].... b[x] in that order. Similarly,
b[x+2] is the concatenation of b[2],b[3]....b[x],b[x+1].
So, basically, b[n] will be concatenation of last x terms of b[i], taken left from right.
Given parameters as p and q as queries, how can I find out which character among b[1], b[2], b[3]..... b[x] does the qth character of b[p] corresponds to?
Note: x and b[1], b[2], b[3]..... b[x] is fixed for all queries.
I tried brute-forcing but the string length increases exponentially for large x.(x<=100).
Example:
When x=3,
b[] = a, b, c, a b c, b c abc, c abc bcabc, abc bcabc cabcbcabc, //....
//Spaces for clarity, only commas separate array elements
So for a query where p=7, q=5, answer returned would be 3(corresponding to character 'c').
I am just having difficulty figuring out the maths behind it. Language is no issue
I wrote this answer as I figured it out, so please bear with me.
As you mentioned, it is much easier to find out where the character at b[p][q] comes from among the original x characters than to generate b[p] for large p. To do so, we will use a loop to find where the current b[p][q] came from, thereby reducing p until it is between 1 and x, and q until it is 1.
Let's look at an example for x=3 to see if we can get a formula:
p N(p) b[p]
- ---- ----
1 1 a
2 1 b
3 1 c
4 3 a b c
5 5 b c abc
6 9 c abc bcabc
7 17 abc bcabc cabcbcabc
8 31 bcabc cabcbcabc abcbcabccabcbcabc
9 57 cabcbcabc abcbcabccabcbcabc bcabccabcbcabcabcbcabccabcbcabc
The sequence is clear: N(p) = N(p-1) + N(p-2) + N(p-3), where N(p) is the number of characters in the pth element of b. Given p and x, you can just brute-force compute all the N for the range [1, p]. This will allow you to figure out which prior element of b b[p][q] came from.
To illustrate, say x=3, p=9 and q=45.
The chart above gives N(6)=9, N(7)=17 and N(8)=31. Since 45>9+17, you know that b[9][45] comes from b[8][45-(9+17)] = b[8][19].
Continuing iteratively/recursively, 19>9+5, so b[8][19] = b[7][19-(9+5)] = b[7][5].
Now 5>N(4) but 5<N(4)+N(5), so b[7][5] = b[5][5-3] = b[5][2].
b[5][2] = b[3][2-1] = b[3][1]
Since 3 <= x, we have our termination condition, and b[9][45] is c from b[3].
Something like this can very easily be computed either recursively or iteratively given starting p, q, x and b up to x. My method requires p array elements to compute N(p) for the entire sequence. This can be allocated in an array or on the stack if working recursively.
Here is a reference implementation in vanilla Python (no external imports, although numpy would probably help streamline this):
def so38509640(b, p, q):
"""
p, q are integers. b is a char sequence of length x.
list, string, or tuple are all valid choices for b.
"""
x = len(b)
# Trivial case
if p <= x:
if q != 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
return p, b[p - 1]
# Construct list of counts
N = [1] * p
for i in range(x, p):
N[i] = sum(N[i - x:i])
print('N =', N)
# Error check
if q > N[-1]:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
print('b[{}][{}]'.format(p, q), end='')
# Reduce p, q until it is p < x
while p > x:
# Find which previous element character q comes from
offset = 0
for i in range(p - x - 1, p):
if i == p - 1:
raise ValueError('q={} out of bounds for p={}'.format(q, p))
if offset + N[i] >= q:
q -= offset
p = i + 1
print(' = b[{}][{}]'.format(p, q), end='')
break
offset += N[i]
print()
return p, b[p - 1]
Calling so38509640('abc', 9, 45) produces
N = [1, 1, 1, 3, 5, 9, 17, 31, 57]
b[9][45] = b[8][19] = b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
Similarly, for the example in the question, so38509640('abc', 7, 5) produces the expected result:
N = [1, 1, 1, 3, 5, 9, 17]
b[7][5] = b[5][2] = b[3][1]
(3, 'c') # <-- Final answer
Sorry I couldn't come up with a better function name :) This is simple enough code that it should work equally well in Py2 and 3, despite differences in the range function/class.
I would be very curious to see if there is a non-iterative solution for this problem. Perhaps there is a way of doing this using modular arithmetic or something...

Resources