0

I'm looking for a more dynamic way to write the following statement.

data = [r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13]] 

r represents my response data coming in, to which I take that and enumerate the items into a dictionary. This works, but its too static. If data is added or removed, the API code then needs to be adjusted to account for it.

What is an intuitive way to handle this? Below is a sample of the full class for reference.

class Pots(Resource):
    def get(self, store):
        print('USAGE: Received a request at POTS for Store ' + store )
        conn = sqlite3.connect('store-db.db')
        cur = conn.cursor()
        cur.execute('SELECT * FROM Pots WHERE StoreNumber like ' + store) 
        res = cur.fetchall()
        if not res:
            print("RESPONSE: No data was found for this request.")
            return('No data was found', 404)
        else:
            for r in res:
                column_names = ["StoreNumber", "ForwardOnFail", "HuntLine","FirePrimary","FireSecondary", "BurglarPrimary", "BurglarSecondary","BurglarTertiary", "DNR", "PassengerElevator", "FreightElevator", "Escalator1", "Escalator2","ShopperTrak"]
                data = [r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13]]         
                datadict = {column_names[itemindex]:item for itemindex, item in enumerate(data)}
                return(datadict, 200)

Edit: Please ignore any SQL inefficiencies. While I appreciate the advice, I am aware and do not intend to use this in production. Just for testing. :)

CodeSpent
  • 1,684
  • 4
  • 23
  • 46
  • 2
    `data = r[:14]`? Or use `zip` to combine `r` and `column_names`, which will discard any mismatches after the shorter list finishes. – jonrsharpe Nov 16 '18 at 11:39
  • you probably should take a look to ORM systems like `sqlalchemy` – Azat Ibrakov Nov 16 '18 at 11:40
  • please fix the SQL injection in your code: `cur.execute('SELECT * FROM Pots WHERE StoreNumber like ' + sto` should be `cur.execute('SELECT * FROM Pots WHERE StoreNumber like ?'. (sto,))` – Uku Loskit Nov 16 '18 at 11:42
  • I suppose what I want to achieve wouldn't really be possible, actually anyways. I wanted to be able to account for expanding/shrinking of the database, however, truple range will become an issue if new data is added with no column name assigned. Hmm. – CodeSpent Nov 16 '18 at 11:42
  • 1
    I agree with slicing, but be aware that depending on the type of `r` (e.g. a numy array) the slice may actually be a view on `r` and not a new list, i.e. modifying `data` may modify `r`. – tobias_k Nov 16 '18 at 11:43
  • 1
    @CodeSpent So this is really an X/Y question... you really do want to just return the row as a column-name to value dict, right? – AKX Nov 16 '18 at 11:43
  • @AKX essentially. Just to respond to the request with more semantically clear JSON. At the end of the day, though, there's more than just this class standing in my way from achieving what I want to, though. – CodeSpent Nov 16 '18 at 11:47
  • uDoes the res variable contain the column names? In other words is there information in the database from which you can dynamically associate the column headers with the data? This seems little too static. – cvanelteren Nov 16 '18 at 11:54

4 Answers4

1

Use slicing r[:14] for this:

print(r[:14])
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
1

Usual list comprehension:

 r = [1, 2, 3] 
 data = [r[0], r[1], r[2]]
 data
 [1, 2, 3]
 data = [r[i] for i in range(len(r)-1)]
 data
 [1, 2, 3]
Howz
  • 61
  • 4
1

You may be looking for something like this.

Notice that we're using the sqlite3.Row row factory so we get row.keys().

I also took the liberty of

  • fixing that SQL injection vulnerability
  • adding the limit clause (because you always only return a single row anyway)
  • using fetchone() instead of fetchall() due to the above.

conn = sqlite3.connect("store-db.db")
conn.row_factory = sqlite3.Row
cur = conn.cursor()
cur.execute(
    "SELECT * FROM Pots WHERE StoreNumber like %s limit 1",
    (store,),
)
row = cur.fetchone()
if not row:
    raise NotImplementedError("...")
data_dict = {key: row[key] for key in row.keys()}
AKX
  • 152,115
  • 15
  • 115
  • 172
  • This is incredibly intuitive and does exactly what I wanted without me being totally clear on requirements. Awesome work, I'll update my post to more concisely explain that this was the result I wanted. – CodeSpent Nov 16 '18 at 11:54
0

Lets say you have something like this (using python shell):

>>> column_names = ["a","b","c"]
>>> data = [1,2,3,4,5,6]
>>> {key:value for key,value in zip(column_names, data)}
{'a': 1, 'b': 2, 'c': 3}
Julio Daniel Reyes
  • 5,489
  • 1
  • 19
  • 23
  • Slicing `data` to the length of `column_names` is unnecessary, as `zip` uses the length of the shortest iterable argument. – AKX Nov 16 '18 at 11:57