I have a string containing a few variables that I would like to store.
data = '{name:ItCameFr0mmars,id:2110939,score:2088205,level:43,l
evelProgress:35,kills:18412,deaths:6821,kdr:2.70,kpg:12.03,spk:
113.42,totalGamesPlayed:1530,wins:913,loses:617,wl:0.60,playTim
e:2d 15h 1m,funds:2265,clan:TyDE,featured:No,hacker:false,follo
wing:0,followers:3,shots:117902,hits:38132,nukes:6,meleeKills:3
77,createdDate:2019-03-13,createdTime:21:38:39,lastPlayedClass:
Triggerman}'
I want to assign a variable for each bit of data. For example:
level = 43
kills = 18412
and so on.
Is there a way to do this, as each example: number would become a variable with that number stored? Also? how could I make a dictionary for it?
Here is a basic parser:
for name, val in [item.split(':', maxsplit=1) for item in data.strip("{}").split(",")]:
globals()[name] = val
print(featured)
If you want to do this in a function. Just replace globals with locals.
Usually it is better to put it into an object:
class Data():
def __init__(self, data):
for name, val in [item.split(':', maxsplit=1) for item in data.strip("{}").split(",")]:
setattr(self, name, val)
obj = Data(data)
print(obj.featured)
Why don't you make it like a dictionary like this
data = {"name":"ItCameFr0mmars","id":2110939,"score":2088205}
So you can get each value based on its key.
data["id"] will be 2110939
And if you want to print all them, you could write
for key,value in data.items():
print(key,":",value)
But I guess this is not what you wanted to do?
Related
I'm loading data about phone calls into a list of namedtuples called 'records'. Each phone call has information on the length of the call in the variable 'call_duration'. However, some have the variable set to None. I would like to replace None with zero in all of the records, but the following code doesn't seem to work:
for r in records:
if r.call_duration is None:
r = r._replace(call_duration=0)
How can replace the value in the list? I guess the problem is that the new 'r' isn't stored in the list. What would be the best way to capture in the change in the list?
You can replace the old record by using its index in the records list. You can get that index using enumerate():
for i, rec in enumerate(records):
if rec.call_duration is None:
records[i] = rec._replace(call_duration=0)
I suggest you create your own class, it will benefit you in the future as far as object management goes. When you want to create methods later on for a record, you'll be able to easily do so in a class:
class Record:
def __init__(self, number = None, length = None):
self.number = number
self.length = length
def replace(self, **kwargs):
self.__dict__.update(kwargs)
Now you can easily manage your records and replace object attributes as you deem necessary.
for r in records:
if r.length is None:
r.replace(length = 0)
I spent my morning reading similar questions/answers (What is the best way to implement nested dictionaries?, Multiple levels of keys and values in Python, Python: How to update value of key value pair in nested dictionary?) but I'm still not able to solve the problem.
I have this tab dictionary with a tuple as key and I want as values: an integer, a dictionary, another dictionary and some lists. Then for every key, something like this: (str,str,str,str):{int, {}, {}, [], [] ...}
I want to be able to update these values structures and I need defaultdict because I don't know all the keys and anyway they are too much to be declared one by one manually.
I'm able to do this for a structure like this (str,str,str,str):{int} in this way:
tab=defaultdict(lambda: defaultdict(int))
tab[key][0]+=1
Or for a structure like this (str,str,str,str):{{}, {}} in this way:
tab=defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
tab[key][1][str]+=1
tab[key][2][str]+=1
But not for what I really need.
Thank you!
Ok, thank to #RemcoGerlich I'm trying to fix the problem, but I never used class before and maybe there's still something wrong in my code... Btw the int is a counter, the two dictionary have ip addresses like keys and the number of occurrences as values.
class flux(object):
def __init__(self, count_flux=0, ip_c_dict=None, ip_s_dict=None):
self.count_flux = count_flux
self.ip_c_dict = ip_c_dict if ip_c_dict is not None else {}
self.ip_s_dict = ip_s_dict if ip_s_dict is not None else {}
def log_to_dict(dir_file,dictionary):
f = gzip.open(dir_file,'r')
for line in f:
line = line.strip('\n')
if not line: break
elements = line.split(" ")
key=elements[40],elements[18],elements[41],elements[37]
dictionary[key].count_flux+=1
dictionary[key].ip_c_dict[elements[0]]+=1
dictionary[key].ip_s_dict[elements[19]]+=1
###Main
tab=defaultdict(flux)
log_to_dict('/home/-/-.txt',tab)
I would create a class for your values, it's obviously complicated.
class YourClass(object):
def __init__(self, anint=0, adict=None, anotherdict=None, somelists=None):
self.anint = anint
self.adict = adict if adict is not None else {}
self.anotherdict = anotherdict if anotherdict is not None else {}
self.somelists = somelists if somelists is not None else []
(don't use {} or [] as default arguments, that leads to them being shared between all instances).
Then you can use a defaultdict(YourClass) and also set things like tab[key].anotherdict[str] ...
I have a class which looks like this.
class CharInStageList(object):
def __init__(self, charid, charname) :
self.charid = charid
self.charname = charname
into this class I would like to add lists that I have.
I know how to do it the normal way
charOne = CharInStageList(1,'Tim')
charTwo = CharInStageList(2,'Struppi')
that's not a problem what I actually want to do is to add them by using a loop.
I get my data in this form
((1,'Tim'),(4,'Struppi'))
or
((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
the amount of characters I have in the scene is always different.
what I imagined would be a loop like this
charlist = ((1,'Tim'),(4,'Struppi'))
for char in charlist
objname = CharInStageList(char[0],char[1])
something like this
I want the objname to change by itself for every object I add to the class.
How can I get this effect?
I can only use python 2.6.6 for this since it's the maya 2013 python
Edit:
Thx #silas-ray #chepner #theodox I looked into Dicts a bit more and that's pretty much what I need
I use a modified version of #chepner method on it.
object_dict = dict( (y, CharInStageList(x,y)) for x,y in data )
Works like a charm
My testcode looks like this
import maya.cmds as cmds
dicttest = {}
def getdata ():
global dicttest
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
dicttest = dict( (y,(x,y)) for x,y in data )
getdata()
def printtest() :
for char in dicttest:
print dicttest[char]
printtest()
dicttest.clear()
I would have liked to comment in your answers with code examples but I can't get that to work there.
Objects are not added to a class. Instead, you can create a list of objects which are all instances of the same class, using a list comprehension and taking advantage of the *args syntax:
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
object_list = [ CharInStageList(*x) for x in data ]
Perhaps you want a dictionary instead:
object_dict = dict( (y, CharInStageList(x,y)) for x,y in data )
(Note that CharInStageList is a poor name for the class, because it's not a list; it encapsulates a single character.)
If you really want CharInStateList to be a collection of characters, try something like this, which is just a thin wrapper around a dictionary:
# Your former CharInStageList
class Character(object):
def __init__(self, charid, charname) :
self.charid = charid
self.charname = char name
class OnStageCharacters(object):
def __init__(self):
self.characters = dict()
# Index on-stage characters using their charid
def add(self, character):
self.characters[character.charid] = character
on_stage = OnStageCharacters()
for id, name in data:
on_stage.add( Character(id, name) )
You can't (at least not without hacking at locals/globals, which is generally not a good idea) change the name you are assigning to dynamically like that. You can, however, insert them in to a dictionary where the keys are your dynamically generated names.
characters = {}
for char_data in char_list:
characters[char_data[1]] = CharInStageList(*char_data)
Though if all your character objects are storing is name and id, it might make more sense to simplify the whole thing and just create mapping dictionaries rather than objects.
character_names_by_id = dict(char_data)
character_ids_by_name = dict((name, id) for id, name in char_data)
#chepner's answer is a great one if you can use the *args form to fill out your class instances.
If you're just asking the most efficient way to do this from a loop, remember you can have iterate over the parts of a tuple together:
data = ((1,'Tim'),(4,'Struppi'),(5,'Nami'),(6,'Luffy'))
class_data = (CharInStageList(id, name) for id, name in data) # "for id, name" will yield two vals
You can also use map, which is very common for doing bulk data translations. A common way to do it is with a lambda so you can write it clearly:
to_char = lambda k: CharInStageList(k[0], k[1])
class_data = map(to_char, data)
If you're doing something as simple as your example, you might not want to bother with your own class. the namedtuple is a great data structure for creating tuples that are easy to work with. It also means you can use positional or named args interchangeably, just as in #chepner's *args version:
StageListChar = namedtuple('CharInStageList', ['id', 'name'])
class_data = map(StageListChar , data)
I am writing a function that will take a parameter and, among other things, make a dictionary. I would like the dictionary's name to be based off the name of the input file. Say ht input file is input.xml , i would like the name of the dictionary to be input. Ideally I would use something like this:
def function(input):
for x in y: list(get value)
input[:4][key] = [value]
I am wondering if you know a better way to do this but what i am using now is an extra name in the function:
def function(input, dictname):
for x in y: list(get value)
dictname[key] = [value]
right now I am simply adding a second name to my function but am wondering if there is a way to do this to require fewer inputs.
Edit
I am including a longer version of the function I am using so you guys can get the context. This uses a BioPython module to iterate through an XML file of hits. I am using [temp] to hold the hits for each query and then making a dictionary of for each set of query/hits. I would like this dictionary to be named the same as my input file.
from Bio.Blast import NCBIXML
def make_blast_dictionary(blastxml, maxhits, blastdict):
temp=[]
for record in NCBIXML.parse(open(blastxml):
for number, align in enumerate(record.alignments):
if number == int(maxhits): break
temp.append(str(align.title).split("|")[1])
blastdict[str(record.query_id)] = [temp]
The thing about named variables is that you can call them whatever you like. It's best to name them specific to the context you're using them with.
It would be a better move to simply return a dictionary from your method, instead.
The other respondents are legitimately concerned about why you would want to do this or whether you should do this. That being said, here is how you could do it:
import os.path
def function(filename):
d = {'red': 10, 'blue': 20}
name, ext = os.path.splitext(filename)
globals()[name] = d
function('input.xml')
print input
def make_name(input):
return = input.split('.')[0]
def function(input):
"""Note: this function is incomplete and assumes additional parameters are in your original script
"""
for x in y: list(get value)
dict_name[key] = [value]
return dict_name
def make_dict(input):
dict_name = make_name(input)
dict_name = {}
dict_name = function(input)
return dict_name
Is this what you need?
I have string variable which contains "variable" like content as shown below.
str1="type=gene; loc=scaffold_12875; ID=FBgn0207418; name=Dvir\GJ20278;MD5=4c62b751ec045ac93306ce7c08d254f9; length=2088; release=r1.2; species=Dvir;"
I need to make variables out of the string such that the variables name and values goes like this
type="gene"
loc="scaffold_12875"
ID="FBgn0207418"
name="Dvir\GJ20278"
MD5="4c62b751ec045ac93306ce7c08d254f9"
length=2088
release="r1.2"
species="Dvir"
Thanks for the help in advance.
Don't do this. You could, but don't.
Instead make a dictionary whose keys are the names:
result_dict = {}
items = str1.split(';')
for item in items:
key, value = item.strip().split('=')
result_dict[key] = value
Or you could do this
class Namespace(object):
pass
for item in str1.split(';'):
key, value = item.strip().split('=', 1)
setattr(Namespace, key, value)
You can then access your variables like so
Namespace.length