
# People who have the same interest with each other


users = [
    { "id": 0, "name": "Hero" },
    { "id": 1, "name": "Dunn" },
    { "id": 2, "name": "Sue" },
    { "id": 3, "name": "Chi" },
    { "id": 4, "name": "Thor" },
    { "id": 5, "name": "Clive" },
    { "id": 6, "name": "Hicks" },
    { "id": 7, "name": "Devin" },
    { "id": 8, "name": "Kate" },
    { "id": 9, "name": "Klein" }
    ]

print("users:")
print(users)

friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3), (3, 4),
    (4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)]

print("\nfriendships:")
print(friendships)

# add a list of friends to each user
for user in users:
   print(user)
   print("Adding attr 'friends' to dict entry")
   user["friends"] = []
   print(user, "\n")

print("users:")
print(users)


# populate the lists using the friendships data:
for i, j in friendships:
    # this works because users[i] is the user whose id is i
    users[i]["friends"].append(users[j])      # add i as a friend of j
    users[j]["friends"].append(users[i])      # add j as a friend of i

print("users:")
print(users)

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Interests
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

# list of pairs (user_id, interest):

interests = [
    (0, "Hadoop"), (0, "Big Data"), (0, "HBase"), (0, "Java"),
    (0, "Spark"), (0, "Storm"), (0, "Cassandra"),
    (1, "NoSQL"), (1, "MongoDB"), (1, "Cassandra"), (1, "HBase"),
    (1, "Postgres"), (2, "Python"), (2, "scikit-learn"), (2, "scipy"),
    (2, "numpy"), (2, "statsmodels"), (2, "pandas"), (3, "R"), (3, "Python"),
    (3, "statistics"), (3, "regression"), (3, "probability"),
    (4, "machine learning"), (4, "regression"), (4, "decision trees"),
    (4, "libsvm"), (5, "Python"), (5, "R"), (5, "Java"), (5, "C++"),
    (5, "Haskell"), (5, "programming languages"), (6, "statistics"),
    (6, "probability"), (6, "mathematics"), (6, "theory"),
    (7, "machine learning"), (7, "scikit-learn"), (7, "Mahout"),
    (7, "neural networks"), (8, "neural networks"), (8, "deep learning"),
    (8, "Big Data"), (8, "artificial intelligence"), (9, "Hadoop"),
    (9, "Java"), (9, "MapReduce"), (9, "Big Data")
    ]

print("\n\nUsers and their interests:")
print(interests)

print("\n\nusers[4]:")
print(users[4])
print("\n\nusers[4].['friends']:")

# print( x['id'] for x in users[4]['friends'] )
for x in users[4]['friends']:
    print("+++ ", x['id'], type(x['id']) )
print()

print(list(x for x in interests if x[0] == 3))
print(list(x for x in interests if x[0] == 5))

print(list(x for x in interests if x[0] == 4))
print(list(x for x in interests if x[0] == 7))

# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# Find people with common interest
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

def data_scientists_who_like(target_interest):
    return [user_id
            for user_id, user_interest in interests
            if user_interest == target_interest]

# People who like 'machine learning'
print("People who like 'machine learning':")
print(data_scientists_who_like('machine learning'))


# ++++++++++++++++++++++++++++++++++++++++++++++++
# Build 2 indexes:
# ++++++++++++++++++++++++++++++++++++++++++++++++

print("\n\n\n\n")

from collections import defaultdict

# Index (1): 
#     keys are interests, values are lists of user_ids with that interest
user_ids_by_interest = defaultdict(list)

# **** I created my own "defaultdict" in DefaultDict.py

for user_id, interest in interests:
    user_ids_by_interest[interest].append(user_id)

import pprint as pp
print("interests:")
pp.pp(interests)

print()

print("user_ids_by_interest:")
pp.pp(user_ids_by_interest)

# Index (2):
#     keys are user_ids, values are lists of interests for that user_id
interests_by_user_id = defaultdict(list)

for user_id, interest in interests:
    interests_by_user_id[user_id].append(interest)


print("interests_by_user_id:")
pp.pp(interests_by_user_id)



# +++++++++++++++++++++++++++++++++++++++++++++++++++++++
# How to use the 2 indexes to do look ups
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++

print("Interests of user[0]:")
print(interests_by_user_id[0])
print("Users with interest 'Hadoop':")
print(user_ids_by_interest['Hadoop'])
print("Users with interest 'Big Data':")
print(user_ids_by_interest['Big Data'])
print("Users with interests of user 0:")

for interested_user_id in interests_by_user_id[0]:
    print(f'{interested_user_id}: {user_ids_by_interest[interested_user_id]}')



from collections import Counter

# def most_common_interests_with(user):
#     return Counter(interested_user_id
#         for interest in interests_by_user_id[user["id"]]
#         for interested_user_id in user_ids_by_interest[interest]
#         if interested_user_id != user["id"])

def most_common_interests_with(user):
    return Counter(interested_user_id
        for i in interests_by_user_id[user["id"]]
        for interested_user_id in user_ids_by_interest[i]
        if interested_user_id != user["id"])

print(most_common_interests_with(users[0]))

# WTF is this ??? I can only do it with loops...

def my_most_common_interests_with(user):
    # print("1:", user)
    # print("2:", user["id"])
    usersInterest = interests_by_user_id[user["id"]]
    print("3:", usersInterest)

    otherUsersWithSameInterest = []
    for interested_user_id in usersInterest:
        print("Adding: ", user_ids_by_interest[interested_user_id])
        for i in user_ids_by_interest[interested_user_id]:
            if (i != user["id"]):
                otherUsersWithSameInterest.append(i)
        print(otherUsersWithSameInterest)
    print(Counter(otherUsersWithSameInterest))
    return Counter(otherUsersWithSameInterest)

# print("==============================================\n\n")
# print(users)
# print("++++++++++++++++++++++++++++++++++++++++++++++\n\n")
# print(users[0])
print(my_most_common_interests_with(users[0]))


