Using dict comprehension to append data

does Ignition not support comprehension? this isn't working, but it's valid code:

#
#	'value' is the entire dataset, we only want the assetName at this point
#
assetNames = {}
py_value = system.dataset.toPyDataSet(value)
for item in py_value:        #     ↓ column    ↓ data
	assetNames = {**assetNames,**{'assetName':item['assetName']}}
return [assetNames]	#<--- cuz everything needs to be a list... :)

i am building a table but only require one column from the dataset to populate the table. this should return a dict of key:value pairs (column and data)... but it isn't.

AFAIK, the table parses a data object of key:value pairs; the key is the column name, the value is, well, the value. this should deliver what the table parser is looking for.

okay. rant over. how do i fix this dang script?

Doesn't work in Python 2, I'm pretty sure.

fffffuuuu.... i keep forgetting that we aren't running Python 3. sorry.

Specifically, the issue is multiple sets of kwargs to the dict comprehension in one go.

1 Like

the issue is how to do it in Python 2. :smiley: because i haven't used 2 for about a decade...
EDIT: ah... yes. great post. thank you.

What were you trying to do exactly ? Make a list of dicts where the keys are the columns names and the values are the values, for each row ?

Something like this ?

headers = value.columnNames
return [dict(zip(headers, row)) for row in system.dataset.toPyDataSet(value)]

But maybe with only specific column/keys ?

okay. read the whole post (very good). but i hit a hiccup: i originally had tried this:

assetNames = {}
py_value = system.dataset.toPyDataSet(value)
for item in py_value:
	assetNames.update({'assetName':item['assetName']})
return [assetNames]	#<--- cuz everything needs to be a list... :P

which, ironically, is EXACTLY what the SO post explained (so i'm not actually an idiot after all...). but it only returned a single element (the LAST element): [{assetName: 70456-20}] so i went the comprehension route. so i'm not sure what's going on here.

Well for each item in the dataset, it will update the same key in your dict, over and over again. So in the end you only have the last one.

2 Likes

He's trying to populate a data property of a table in perspective. So I believe he may actually want a list of dictionaries in that case right?

i was, as i mentioned, trying to build a table but only using ONE of the columns of data. so i don't know if your method would work, but i'll give it a shot with an explicitheader definition and see what happens. i am not familiar with the dict method or what it does... so some reading first??? nah. slam it in there!! learn from the pieces!! :smiley:

yes. that's correct.

Think you may want something like this instead then
return [{"assetName":row["assetName"]} for row in system.dataset.toPyDataSet(value)]

:man_facepalming: I HATE PYTHON 2...

If the key is always the same, then it HAS to be a list of dicts.

@ian.sebryk : doing things in just one expression is my jam, my peanut butter, my cheese and beer all combined.

return [{column_name: val} for val in ds.getColumnAsList(ds.getColumnIndex(column_name))]

It does the exact same thing in python 3 though.

3 Likes

but i haven't used update in forever because i just use comprehensions... :stuck_out_tongue:

EDIT: jam, peanut butter, cheese, and beer... now i'm hungry. :smiley:

You can use them in python 2 as well. No issue here.

try the line I posted above.

And if you want to update a dict in just one expression without having to use update, which is a pain to use in comprehension anyway because it doesn't return the updated dict:

new_dict = dict(new_key=some_value, **old_dict)

this can be used in comprehension easily

[dict(k=v, **old_dict) for k, v other_dict.items()]
{k:v for k, v in dict.items()}

absolutely works in python 2. What do you call comprehension ?

2 Likes

dict comprehensions didn't exist until Python 3. which is why my original code didn't work: we're running Python 2.

at any rate, it doesn't work, so i'm trying your code now... stdby. :clock10:

EDIT: *boop* that worked.

You may not be able to do them with the **someDict but you can certainly make dicts on the fly with comprehensions as @PGriffith did in this post , kind of related as well with going from a ds to a dict

Though maybe this counts as a list comprehension, but if the final result is a dict, its a dict comprehension in my book lol.

okay. so what i'm learning here is:

  • data visualization tools in Ignition scripting still suck (Python β†’ prettyPrint, c'mon)
  • i need more prayers to God that my higher-ups let me implement a better IDE strategy soon
  • β†’ i don't need to convert everything to py_dataset ←
  • i may actually commit seppuku before i get my head around this environment

thank you for all your help and comments. very helpful at keeping the blade at bay. :wink:

EDIT: i've always had difficutly visualizing anything, period. once it does click, though, it stays forever. so please bear with as i keep trying to 'see' how this stuff hangs together. very irritating disability for a coder... meditation? forget it.

1 Like

Regarding pretty printing of (assuming) dictionaries hopefully eases your pain a bit, I keep this in a project library so I can call it when needed.

import pprint

mydict = {'nest0':'hi',
		'nest1':{'something':1},
		'nest2':{'nest1again':{'somethingelse':'bye'}}
		}

pp = pprint.PrettyPrinter(depth=4)
pp.pprint(mydict)

image

In my experince PyDataSets are most useful when you want access to all or almost all columns in a dictionary. So for things like

for (someCol1, someCol2, someCol3) in system.dataset.toPyDataSet(ds):
    # do something with your extracted columns
    # don't need to fetch them via col1=row['someCol1']
    # or via col1 = ds.getValueAt(row,'someCol1') if a basic dataset

it's very useful.

1 Like