#!/bin/env python3

import random
import sys
import json
import itertools
import functools
from operator import itemgetter, attrgetter

def get_status(c):
    return c['status'];

jfile = "qq.json"
city_list = json.loads(open(jfile,'r').read())

# entire dictionary
print("Dictionary: ")
for c in city_list:
  print (c)

# detailed info, iterating over dict
for c in city_list:
    print("....................")
    for k, v in c.items():
        print(k, " => ", v)

# -------------------------------------------------------
# data processing, proper
print ("Sorting by rank  ...")
city_sorted = city_list
# ok but verbose:
# city_sorted.sort(key=functools.cmp_to_key(lambda c, d: c['rank']<d['rank'])) # specify a function to use for comparison
city_sorted.sort(key=lambda c: c['rank'])                                      # specify the field to sort by
# works on objects, not dicts: city_sorted.sort(key=attrgetter('rank'))

# Print info for all entries
for c in city_sorted:
    # print("....................")
    print("The " + c['status'] + " of " + c['name'] + " in council " + c['council'] + " has a population of " + str(c['pop']))

# Main task: combined population of top 50 cities/towns (explicit loop)
# Verbose version, using an explicit loop
sum = 0
for c in city_sorted:
     if (c['rank'] <= 50):
         sum += int(c['pop'])

# # version with data cleansing; not needed for final version of the script
# for c in city_sorted:
#     ## skip entries where 'pop' is non-numeric; not necessary on cleansed data
#     if (any(map(lambda c: c.isalpha(), list(c['pop'])))):
#        continue
#     if (c['rank'] <= 50):
#         sum += int(c['pop'].replace(",",""))

print("The total population of the 50 largest cities/towns is: " + str(sum))

# Main task: combined population of top 50 cities/towns (using pre-defined higher-order functions)
# Functional version
# NB: could replace the first 'lambda ..' with 'operator.add'
s = functools.reduce( lambda s, x: s + x
                    , map ( lambda c: int(c['pop']) 
                          ,  city_sorted) )

print("The total population of the 50 largest cities/towns is: " + str(s))
# Done
# -------------------------------------------------------

# # combined population of top 50 cities/towns (using pre-defined higher-order functions)
# # this removes the ',' in an integer for population: not needed in the final version
# s = functools.reduce( lambda s, x: s + x
#       , map ( lambda c: int(c['pop'].replace(",",""))
#             , filter(lambda city: (not any(map(lambda c: c.isalpha(), list(city['pop']))))
#                      , city_sorted)))
# print("The total population of the 50 largest cities/towns is: " + str(s))

# # it = city_list.iter()
# print("Grouped by status: ")
# for s, cs in itertools.groupby(city_list, get_status): # (lambda city: city['status']) )
#     print (s)
#     for c in cs:
#         print (c)

