0

The objective of my problem is to read in a thread post such as this:

([
{
    'title': 'Invade Manhatten, anyone?',
    'tags': ['world-domination', 'hangout'],
    'posts': [
        {
            'author': 'Mr. Sinister',
            'content': "I'm thinking 9 pm?",
            'upvotes': 2,
        },
        {
            'author': 'Mystique',
            'content': "Sounds fun!",
            'upvotes': 0,
        },
        {
            'author': 'Magneto',
            'content': "I'm in!",
            'upvotes': 0,
        },
    ],
}

]))

And create a definition to output this:

[('Mr. Sinister', '2', 'Cautioiusly Evil'), ('Magneto', '0', 'Insignificantly Evil'), ('Mystique', '0', 'Insignificantly Evil')]

Where the list is sorted from highest upvotes to lowest upvotes, with ties broken alphabetically.

However, when I was given this thread:

([
{
    'title': 'Invade Manhatten, anyone?',
    'tags': ['world-domination', 'hangout'],
    'posts': [
        {
            'author': 'Mr. Sinister',
            'content': "I'm thinking 9 pm?",
            'upvotes': 2,
        },
        {
            'author': 'Mr. Sinister',
            'content': "Sounds fun!",
            'upvotes': 0,
        },
        {
            'author': 'Mr. Sinister',
            'content': "I'm in!",
            'upvotes': 0,
        },
    ],
}

]))

Where the author posts multiple times, my program outputs:

[('Mr. Sinister', '2', 'Cautioiusly Evil'), ('Mr. Sinister', '0', 'Insignificantly Evil'), ('Mr. Sinister', '0', 'Insignificantly Evil')]

My program prints each individual post rather than combining the results like this:

[('Mr. Sinister', 2, 'Cautiously Evil')]

Just to clarify, if the thread was:

([
{
    'title': 'Invade Manhatten, anyone?',
    'tags': ['world-domination', 'hangout'],
    'posts': [
        {
            'author': 'Mr. Sinister',
            'content': "I'm thinking 9 pm?",
            'upvotes': 2,
        },
        {
            'author': 'Loki',
            'content': "Sounds fun!",
            'upvotes': 2,
        },
        {
            'author': 'Mr. Sinister',
            'content': "I'm in!",
            'upvotes': 2,
        },
        {
            'author': 'Loki',
            'content': "I'm in it!",
            'upvotes': 20,
        },

    ],
}

]))

It should input:

[('Loki', 22, 'Justifiably Evil'), ('Mr. Sinister', 4, 'Cautiously Evil')]

My code for this is here:

  def author_rankings(thread_list):
# TODO: Determine (author, upvotes, ranking) over all threads.
counterA = 0
counterB=2

listA = []
Final = []
Double = {}
for i in thread_list[0]['posts']:
    for ii in i:
        if ii == 'content':
            null = 1
        else:
            b = str(i[ii])
            if b in Double:
              Double[b]
            a = b
            if a.isdigit():
              a = int(a)
            listA.append(a)
bel=[]
for qq in listA:
    if counterA == counterB:
        bel = []
        counterB+=2
    if counterA%2 ==0:
         bel.append(qq)
         counterA+=1
    else:
       bel.append(qq)
       qq = int(qq)
       if qq == 0:
           bel.append('Insignificantly Evil')

     elif qq < 20:
          bel.append('Cautiously Evil')


     elif qq < 100:
          bel.append('Justifiably Evil')

     elif qq < 500:
           bel.append('Wickedly Evil')

     elif qq >= 500:
          bel.append('Diabolically Evil')

     counterA+=1



     tuuple = tuple(bel)
     Final.append(tuuple)



Final.sort()      

Final.sort(key=lambda tup: -tup[1])

I know I code slightly un-pythonic/ hard to read. Sorry for the inconvenience.

Thank you!

Hayton Lam
  • 31
  • 7
  • 1
    Do you want to sum the upvotes for an _author_? – wwii Aug 09 '17 at 22:24
  • 1
    I'm sorry, this thing is just unreadable, it's not "slightly un-pythonic" it's the devils work. Can't you at least give meaningful names and such? make our life easier while trying to help? – Dror Av. Aug 09 '17 at 22:25
  • @droravr Sorry! I changed the variables to more understandable names. – Hayton Lam Aug 09 '17 at 22:40
  • Iterate over the posts and keep the data in a dictionary of `author:upvote` pairs, adding upvotes during the iteration. You will have to account for missing keys with the dictionary get method or testing first or catching the KeyError or using a collections dictionary container. When the posts are finished iterate over the dictionary items and construct tuples by adding the appropriate *evilness*. – wwii Aug 09 '17 at 23:04
  • https://docs.python.org/3/howto/sorting.html – wwii Aug 09 '17 at 23:07

3 Answers3

0

I do not understand what you are asking, because the logic isn't very clear.

However, the aggregation can be done like so:

some_pages = [
        {
            'title': 'Invade Manhatten, anyone?',
            'tags': ['world-domination', 'hangout'],
            'posts': [
                {
                    'author': 'Mr. Sinister',
                    'content': "I'm thinking 9 pm?",
                    'upvotes': 2,
                },
                {
                    'author': 'Mr. Sinister',
                    'content': "Sounds fun!",
                    'upvotes': 0,
                },
                {
                    'author': 'Mr. Sinister',
                    'content': "I'm in!",
                    'upvotes': 0,
                },
            ],
        }
    ]

author_aggregation = {}
for pages in some_pages:
    for post in pages.get('posts', []):
        a = post.get('author')
        v = post.get('upvotes')
        c = post.get('content')
        if a in author_aggregation:
            author_aggregation.update({a: {'upvotes': author_aggregation[a]['upvotes'] += v, 'content': author_aggregation[a]['content'].append(c)}})
        else:
            author_aggregation[a] = {'upvotes': v, 'content': [c]}

Related:

jmunsch
  • 22,771
  • 11
  • 93
  • 114
0

This might work, it ignores content (can be added as well if needed), only takes upvotes and author. It also uses a dictionary and not a list:

authors = dict()

for post in x[0]['posts']:
    try:
        authors[post['author']] += post['upvotes']

    except KeyError:
        authors[post['author']] = post['upvotes']

for k, upvotes in authors.iteritems():
    if upvotes == 0:
        authors[k] = (upvotes, "Insignificantly Evil")

    elif upvotes < 20:
        authors[k] = (upvotes, "Cautioiusly Evil")

    elif upvotes < 100:
        authors[k] = (upvotes, "Justifiably Evil")

    elif upvotes <= 500:
        authors[k] = (upvotes, "Wickedly Evil")

    elif upvotes > 500:
        authors[k] = (upvotes, "Diabolically Evil")

print authors

Outputs:

{'Mr. Sinister': (2, 'Cautioiusly Evil')}

And:

{'Mr. Sinister': (4, 'Cautioiusly Evil'), 'Loki': (22, 'Justifiably Evil')}

For the 2nd example.

Dror Av.
  • 1,184
  • 5
  • 14
0

This code works, hopefully it is readable enough so you can adapt it

x = in[0]  # returns a dict from your input

for post in x.get('posts'):
        author = post.get('author')
        if author not in d.keys():
            d[author] = post
        else:
            d.get('author')['upvotes'] += post.get('upvotes')

This will return a dict without duplicate authors and won't update the score if it is already there.

I tried it on your data and it worked

d {'Mr. Sinister': {'content': "I'm thinking 9 pm?", 'upvotes': 2, 'author': 'Mr. Sinister'}}

Chen A.
  • 10,140
  • 3
  • 42
  • 61
  • Your code doesn't count all the votes of the same poster. It will just take the votes from the first post of each author. – Dror Av. Aug 09 '17 at 22:54