1

I'm trying to create a simple bot for tallying requests for reviews of ticker symbols.

there's a small community of traders who make requests for the TA expert to analyze charts. This is going to run as a discord bot.

I want to create an dictionary something like

poll[ticker][user] = 1

this way it will hold an dictionary of dictionary of users keyed off the ticker symbol.

this is so ticker requests can not be duplicated and a user cannot vote for the same ticker twice.

I'm then going to save it in the key store on Repl.it

This is my second day with python although i have coded in other languages before but just not for many years.. just wanted to make sure i was on the right track.

Users will enter their votes like:

!v ZRX

Ultimately we will want to see the results like:

!pollresults

ZRX : MoonRaccoon, Dontcallmeskaface, TheDirtyTree
LINK : MoonRaccoon, TheDirtyTree
XRP: Dontcallmeskaface

So I figured the best data structure to support this would be something like:

poll = {'ZRX' : {'MoonRaccoon' : 1, 'Dontcallmeskaface' : 1, 'TheDirtyTree' : 1}, 'LINK' : {'MoonRaccoon' : 1, 'TheDirtyTree' : 1}, 'XRP' : {'Dontcallmeskaface'} : 1}

Does this make sense?

client = discord.Client()

def update_poll(ticker,requestor):
  vote = {ticker : {requestor : 1}}
  if "poll" in db.keys():
    db["poll"].setdefault(ticker, {})[requestor] = 1
  else:
    db["poll"] = vote


@client.event
async def on_ready():
  print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
  if message.author == client.user:
    return

  msg = message.content
 
  if msg.startswith("!v"):
    ticker = msg.split("!v ",1)[1]
    author = str(message.author).split("#",1)[0]
    update_poll(ticker,author)
     
    await message.channel.send("vote for " + ticker + " by " + author + " added.")
    await message.channel.send(db["poll"])

  if msg.startswith("!clear"):
    
    db["poll"] = {}
    
    await message.channel.send("poll cleared")
    await message.channel.send(db["poll"])


I set db = {} and it doesn't seem to be adding any votes to it now.

output every time of the data structure is the same no matter who i vote for. :

!v MATIC

vote for MATIC by MoonRaccoon added.
{}

3 Answers3

1

Try this

def update_poll(ticker,requestor):
  vote = {ticker : {requestor : 1}}
  if "poll" in db.keys():
    db["poll"].setdefault(ticker, {})[requestor] = 1
  else:
    db["poll"] = vote

Edit: The above answer assumed you were using the builtin dictionary Not sure whether replit.db has the setdefault method. Try this:-

def update_poll(ticker,requestor):
  vote = {ticker : {requestor : 1}}
  if "poll" in db.keys():
    if ticker in db["poll"].keys():
      db["poll"][ticker][requestor] = 1
    else:
      db["poll"][ticker] = {}
      db["poll"][ticker][requestor] = 1
  else:
    db["poll"] = vote
Abdul Aziz Barkat
  • 19,475
  • 3
  • 20
  • 33
0

To assign db["poll"][ticket][requestor], it tries to first get db["poll"][ticker] but doesn't find it, so it raises the error.

You need to create db["poll"][ticker] before assigning db["poll"][ticker][requestor].

As a side note, there are two cleaner ways to achieve what you want to do: you might want to read up on defaultdict or create a custom dataclass object using Pydantic or something like that.

Jabrove
  • 718
  • 5
  • 13
  • Yes. I'm trying to create it.. I just don't know how I guess. seems to me this would work fine in PHP. – Robin Goodheart Jan 12 '21 at 16:45
  • You never assigned db["poll"][ticker]. You need to do that before assigning db["poll][ticker][requestor]. – Jabrove Jan 12 '21 at 16:51
  • This needs to work with the database described here.. not sure how custom dataclass would work with that.. but none of these solutions have worked so far either. https://docs.repl.it/misc/database – Robin Goodheart Jan 13 '21 at 04:12
0

You could use a nested defaultdict like specified in Nested defaultdict of defaultdict.

from collections import defaultdict

my_dict = defaultdict(lambda: defaultdict(dict))

my_dict['poll']['ZRX']['my user name']=1