-1

I need to display notifications in Facebook format using python. But finding it difficult to group the items. Following is the list from query

sample list

The notification must be displayed as follows

  • John changed Name, Code, Description of Product Shirt
  • John changed Name of Product Hat
  • John changed Variant Code of Hat
  • Mike changed Name of Product Trouser, Hat
  • Kiet changed Name of Variant XXL Shirt

Is there any possibility of doing this using python group by? and order by date?

Vyas Rao
  • 478
  • 6
  • 10
  • 25
  • What is the python data structure that the items are in? A 2-dimensional list? A dictionary? It is hard to answer the question when you have only posted an image – Jeff Mandell Nov 10 '16 at 07:10
  • @JeffMandell items are from SQLAlchemy result, could be converted to a list. – Vyas Rao Nov 10 '16 at 07:11

2 Answers2

1

Basically you need to reduce the rows to be rows that have the same user and product name values. I am using a dictionary (default dict) to map the user/product name to a list of their changed elements.

from collections import defaultdict
# Assuming your datastructure looks like:
rows = [['jeff', 'product', 'name', 'shirt'], ['jeff', 'product', 'code', 'shirt'], ['mike', 'product', 'name', 'trouser']]
user_index = 0
changed_index = 2
product_name_index = 3

delimeter = '&&&'
changed_items = defaultdict(list)
for row in rows:
    key = '%s%s%s' % (row[user_index], delimeter, row[product_name_index])
    changed_items[key].append(row[changed_index])

for key, changed in changed_items.iteritems():
    user, product = key.split(delimeter)
    print('%s changed %s of %s' % (user, ', '.join(changed), product))

If you want it sorted by order, you will have to use a default AND ordered dictionary. You can use this implementation of said data structure: https://stackoverflow.com/a/6190500/3741585

Community
  • 1
  • 1
Jeff Mandell
  • 863
  • 7
  • 16
1

You could try the following approach using groupby, which seems to work for your existing data but might need further thought for other edge cases:

from itertools import groupby
from datetime import datetime

results = [
    ["User", "Type", "Changed", "Product Name", "Date"],
    ["John", "Product", "Name", "Shirt", "1-Jan-17"],
    ["John", "Product", "Code", "Shirt", "1-Jan-17"],
    ["John", "Product", "Description", "Shirt", "1-Jan-17"],
    ["John", "Product", "Name", "Hat", "1-Jan-17"],
    ["John", "Variant", "Code", "XXL Shirt", "1-Jan-17"],
    ["Mike", "Product", "Name", "Trouser", "2-Jan-17"],
    ["Mike", "Product", "Name", "Tie", "3-Jan-17"],
    ["Kiet", "Variant", "Name", "XXL Shirt", "4-Jan-17"]]

sorted_results = sorted(results[1:], key=lambda x: (datetime.strptime(x[4], '%d-%b-%y'), x[0]))

for k1, g1 in groupby(sorted_results, lambda x: x[0]):
    grouped_by_name = list(g1)
    v1, v2 = [], []

    for k2, g2 in groupby(grouped_by_name, lambda x: (x[1], x[3])):  # type, name
        v1.append(list(g2))

    for k2, g2 in groupby(grouped_by_name, lambda x: (x[1], x[2])):  # type, changed
        v2.append(list(g2))

    if len(v1) < len(v2):
        for entry in v1:
            entries = [changed for user, ptype, changed, pname, date in entry]
            print("{} changed {} of {} {}".format(entry[0][0], ', '.join(entries), entry[0][1], entry[0][3]))
    else:
        for entry in v2:
            entries = [pname for user, ptype, changed, pname, date in entry]
            print("{} changed {} of {} {}".format(entry[0][0], entry[0][2], entry[0][1], ', '.join(entries)))

This would display the following output:

John changed Name, Code, Description of Product Shirt
John changed Name of Product Hat
John changed Code of Variant XXL Shirt
Mike changed Name of Product Trouser, Tie
Kiet changed Name of Variant XXL Shirt
Martin Evans
  • 45,791
  • 17
  • 81
  • 97