Skip to content
Python programming examples in q

Dictionary programs

From GeeksforGeeks Python Programming Examples

Follow links to the originals for more details on the problem and Python solutions.

Sort dictionary by keys or values

Sort keys ascending

>>> kv = {2:'56', 1:'2', 5:'12', 4:'24', 6:'18', 3:'323'}

>>> sorted(kv.keys())
[1, 2, 3, 4, 5, 6]
q)kv:2 1 4 5 6 3!64 69 23 65 34 76

q)asc key kv
`s#1 2 3 4 5 6

A dictionary is a mapping between two lists: the keys and the values. Keys are commonly of the same datatype; as are values. So most dictionaries are a mapping between two vectors. (Homogenous lists.) Above, dictionary kv is formed from two vectors by the Dict operator !.

A list of key-value pairs can be flipped into two lists, and passed to (!). to form a dictionary.

q)(!).flip(2 56;1 2;5 12;4 24;6 18;3 323)
2| 56
1| 2
5| 12
4| 24
6| 18
3| 323

Sort entries ascending by key

>>> [[k, kv[k]] for k in sorted(kv.keys())]
[[1, 2], [2, 56], [3, 323], [4, 24], [5, 12], [6, 18]]
q)k!kv k:asc key kv
1| 2
2| 56
3| 323
4| 24
5| 12
6| 18

Sort entries ascending by value

>>> sorted(kv.items(), key = lambda x:(x[1], x[0]))
[(1, 2), (5, 12), (6, 18), (4, 24), (2, 56), (3, 323)]
q)asc kv
1| 2
5| 12
6| 18
4| 24
2| 56
3| 323

The value of kv is the dictionary’s values.

q)value kv
56 2 12 24 18 323

So an ascending sort of the dictionary returns it in ascending order of values.

Sum of values

>>> d = {'a': 100, 'b':200, 'c':300}

>>> sum([v for k, v in d.items()])
600

Dictionaries are first-class objects in q, and keywords apply to their values.

q)d:`a`b`c!100 200 300

q)sum d
600

Delete an entry

>>> d = {"Arushi" : 22, "Anuradha" : 21, "Mani" : 21, "Haritha" : 21}

>>> # functional removal
>>> {key:val for key, val in d.items() if key != 'Mani'}
{'Arushi': 22, 'Anuradha': 21, 'Haritha': 21}

>>> # removal in place
>>> del d['Mani']
>>> d
{'Arushi': 22, 'Anuradha': 21, 'Haritha': 21}
q)d:`Anuradha`Haritha`Arushi`Mani!21 21 22 21

q)delete Mani from d        / functional removal
Anuradha| 21
Haritha | 21
Arushi  | 22

q)delete Haritha from `d    / removal in place
`d
q)d
Anuradha| 21
Arushi  | 22
Mani    | 21

Removal in place in q is effectively restricted to global tables. Within functions, use functional methods.

Sort list of dictionaries by value

>>> lis = [{ "name" : "Nandini", "age" : 20},
... { "name" : "Manjeet", "age" : 20 },
... { "name" : "Nikhil" , "age" : 19 }]
>>>
>>> sorted(lis, key=itemgetter('age', 'name'))
[{'name': 'Nikhil', 'age': 19}, {'name': 'Manjeet', 'age': 20}, {'name': 'Nandini', 'age': 20}]
>>> sorted(lis, key=itemgetter('age'),reverse = True)
[{'name': 'Nandini', 'age': 20}, {'name': 'Manjeet', 'age': 20}, {'name': 'Nikhil', 'age': 19}]

A list of q same-key dictionaries is… a table.

q)show lis:(`name`age!(`Nandini;20); `name`age!(`Manjeet;20); `name`age!(`Nikhil;19))
name    age
-----------
Nandini 20
Manjeet 20
Nikhil  19
q)lis iasc lis`age              / sort ascending by age
name    age
-----------
Nikhil  19
Nandini 20
Manjeet 20

q)lis{x iasc x y}/`name`age     / sort by name within age
name    age
-----------
Nikhil  19
Manjeet 20
Nandini 20

Merge two dictionaries

def merge(dict1, dict2):
    d = {}
    d.update(dict1)
    d.update(dict2)
    return d
>>> d1 = {'a': 10, 'b': 8, 'c': 42}
>>> d2 = {'d': 6, 'c': 4}

>>> merge(d1, d2)
{'a': 10, 'b': 8, 'c': 4, 'd': 6}

The Join operator (,) in q has upsert semantics.

q)d1:`a`b`c!10 8 42
q)d2:`d`c!6 4

q)d1,d2
a| 10
b| 8
c| 4
d| 6

Grade calculator

grades.py

jack = { "name":"Jack Frost",
        "assignment" : [80, 50, 40, 20],
        "test" : [75, 75],
        "lab" : [78.20, 77.20]
    }

james = { "name":"James Potter",
        "assignment" : [82, 56, 44, 30],
        "test" : [80, 80],
        "lab" : [67.90, 78.72]
        }

dylan = { "name" : "Dylan Rhodes",
        "assignment" : [77, 82, 23, 39],
        "test" : [78, 77],
        "lab" : [80, 80]
        }

jess = { "name" : "Jessica Stone",
        "assignment" : [67, 55, 77, 21],
        "test" : [40, 50],
        "lab" : [69, 44.56]
    }

tom = { "name" : "Tom Hanks",
        "assignment" : [29, 89, 60, 56],
        "test" : [65, 56],
        "lab" : [50, 40.6]
    }

def get_average(marks):
    total_sum = sum(marks)
    total_sum = float(total_sum)
    return total_sum / len(marks)

def calculate_total_average(students):
    assignment = get_average(students["assignment"])
    test = get_average(students["test"])
    lab = get_average(students["lab"])

    # Result based on weightings
    return (0.1 * assignment +
            0.7 * test + 0.2 * lab)

def assign_letter_grade(score):
    if   score >= 90: return "A"
    elif score >= 80: return "B"
    elif score >= 70: return "C"
    elif score >= 60: return "D"
    else : return "E"

def class_average_is(student_list):
    result_list = []

    for student in student_list:
        stud_avg = calculate_total_average(student)
        result_list.append(stud_avg)
        return get_average(result_list)

students = [jack, james, dylan, jess, tom]

for i in students :
    print(i["name"])
    print("=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=")
    print("Average marks of %s is : %s " %(i["name"],
                        calculate_total_average(i)))

    print("Letter Grade of %s is : %s" %(i["name"],
    assign_letter_grade(calculate_total_average(i))))

    print()

class_av = class_average_is(students)

print( "Class Average is %s" %(class_av))
print("Letter Grade of the class is %s "
        %(assign_letter_grade(class_av)))
$ python3 grades.py
Jack Frost
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Average marks of Jack Frost is : 72.79
Letter Grade of Jack Frost is : C

James Potter
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Average marks of James Potter is : 75.962
Letter Grade of James Potter is : C

Dylan Rhodes
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Average marks of Dylan Rhodes is : 75.775
Letter Grade of Dylan Rhodes is : C

Jessica Stone
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Average marks of Jessica Stone is : 48.356
Letter Grade of Jessica Stone is : E

Tom Hanks
=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
Average marks of Tom Hanks is : 57.26
Letter Grade of Tom Hanks is : E

Class Average is 72.79
Letter Grade of the class is C

Median not average

The output above displays the class median score and letter grade, not the average. Oops.

Shorter programs are easier to get right.

grades.q

/ grade calculator
students:flip`name`assignment`test`lab!flip(
  (`JackFrost;    80 50 40 20; 75 75; 78.20 77.20);
  (`JamesPotter;  82 56 44 30; 80 80; 67.90 78.72);
  (`DylanRhodes;  77 82 23 39; 78 77; 80 80);
  (`JessicaStone; 67 55 77 21; 40 50; 69 44.56);
  (`TomHanks;     29 89 60 56; 65 56; 50 40.6)
  )

students[`mark]:sum .1 .7 .2*(avg'')students `assignment`test`lab
lg:{"EDCBA"sum 60 70 80 90<\:x}  / letter grade from mark
update letter:lg mark from `students;

show students
"Class average: ",string ca:avg students`mark
"Class letter grade: ",lg ca
q)\l grades.q
name         assignment  test  lab        mark   letter
-------------------------------------------------------
JackFrost    80 50 40 20 75 75 78.2 77.2  72.79  C
JamesPotter  82 56 44 30 80 80 67.9 78.72 75.962 C
DylanRhodes  77 82 23 39 78 77 80   80    75.775 C
JessicaStone 67 55 77 21 40 50 69   44.56 48.356 E
TomHanks     29 89 60 56 65 56 50   40.6  57.26  E
"Class average: 66.0286"
"Class letter grade: D"

Mirror characters in a string

def mirrorChars(s, k):
    original = 'abcdefghijklmnopqrstuvwxyz'
    reverse  = 'zyxwvutsrqponmlkjihgfedcba'
    m = dict(zip(original,reverse))

    lst = list(s)
    ti = range(k-1, len(lst))
    for i in ti: lst[i] = m[lst[i]]
    return ''.join(lst)
>>> mirrorChars('paradox', 3)
'paizwlc'
mirrorChars:{[s;k]
  m:{x!reverse x}.Q.a;      / mirror dictionary
  ti:(k-1)_ til count s;    / target indexes
  @[s;ti;m] }
q)mirrorChars["paradox";3]
"paizwlc"

Python and q solutions implement the same strategy:

  • write a mirror dictionary m
  • identify the indexes to be targeted ti
  • replace the characters at those indexes with their mirrors

The Python has the further steps of converting the string to a list and back again.

Count frequency

>>> lst = ([1, 1, 1, 5, 5, 3, 1, 3, 3, 1, 4, 4, 4, 2, 2, 2, 2])

>>> from collections import Counter
>>> Counter(lst)
Counter({1: 5, 2: 4, 3: 3, 4: 3, 5: 2})
q)lst:1 1 1 5 5 3 1 3 3 1 4 4 4 2 2 2 2

q)count each group lst
1| 5
5| 2
3| 3
4| 3
2| 4

Tuples to dictionary

>>> tups = [("akash", 10), ("gaurav", 12), ("anand", 14), ("suraj", 20), 
... ("akhil", 25), ("ashish", 30)]

>>> {t[0]:t[1] for t in tups}
{'akash': 10, 'gaurav': 12, 'anand': 14, 'suraj': 20, 'akhil': 25, 'ashish': 30}
q)tups:(("akash";10);("gaurav";12);("anand";14);("suraj";20);("akhil";25);("ashish";30))

q)(!).flip tups
"akash" | 10
"gaurav"| 12
"anand" | 14
"suraj" | 20
"akhil" | 25
"ashish"| 30

Here we flip the tuples to get two lists, which we pass to Apply (.) as the arguments to Dict (!).

The heading suggests a more general problem than turning a list of pairs into a dictionary. In q, the general case, with tuples of unspecified length, is handled by keyed tables.