Unable to print value from inside array - python

I have an array in which has multiple objects inside it, I want to parse it to give me the value of bar that is in each object.
This is a mock of the array/object I am trying to parse to get the values from.
[
{
foo: [
{
bar: 50,
crow: true
}
]
}
...
{}
...
]
So far this is as far as I have come on the code and admittedly it isn't very far as I've been back tracking as things go wrong and worse.
for foo in response:
print foo
foo_list = list(foo)
print(foo_list[0])
This outputs the whole value of foo then it outputs only the key foo
PS I know this is a repeat question, please only mark as so if the repeat one has the exact format I am looking for.

You want something along the lines of
something[0]['foo'][0]['bar']
The '[' means you need to access an element of a list. The [0] gets the first element of a list.
The '{' means you need to access an entry of a dictionary. The ['foo'] means get the value of key 'foo'.
Your sample above has a dict in a list in a dict in a list.
You should also not scrimp when it comes to error checking... The above could easily be:
sentinel = object() # unique object for checking default from get()
bar = None
if isinstance(something, list) and len(something) == 1:
elem = something[0]
if isinstance(elem, dict):
val = elem.get('foo', sentinel)
if val is not sentinel:
# and so on and so on...
The other thing to mention is that sometimes you don't care about the name of the key. Instead of saying dick.get(key), which requires knowing the key, you can say dick.values()[0]
So, the top could also be:
something[0].values()[0][0].values()[0]
Again, don't skimp on the error checking...

I'm going to assume you want the inner values. Try this code:
response = [{'foo': [ { 'bar': 50, 'crow': True } ] }]
for i in range(len(response)):
for key in response[i].keys():
for d in response[i][key]:
print(list(d.values()))
Basically, what's happening here is we're first iterating through the outer list ([]), then iterating the keys in that array, then iterating each item in that value list for key foo, then printing a list of the dictionary's values. You could also just grab the whole dict as d.
Also, if this is JSON, you're going to want to parse it first with the json lib. See https://docs.python.org/3/library/json.html for more information on that.

Related

Python - How to change dictionary value dynamically

I am trying to use a dictionary in such a way so that it returns a value dynamically. The following code should print "hello" first, then "world". As of now, it prints "hello" two times. Is there a way for me to use this dictionary dynamically?
val = "hello"
test = {
"A" : val
}
print(test["A"])
val="world"
print(test["A"])
I am thinking that this is not correct use of dictionaries. Could you please the whole task?
You can also check values and change the dictionary value
val = "hello"
test = {
"A" : val
}
print(test["A"])
val="world"
if test["A"]!=val: test["A"]=val
print(test["A"])
instead of val="world" use test["A"] = "world"
val = "world" assigns a new string to the variable, but doesn't change the existing string. The dictionary test however keeps the old string value, not a reference to the val variable. You need to use another mutable data structure if you want to update the dictionary like this. Just for illustration, I show how a list would work:
val = ["hello"]
test = { "A" : val }
print(test["A"][0])
val[0] = "world"
print(test["A"][0])
Unlike a string, a list can be updated. test keeps the same (list) value as val (there is only one list in this example), but val is changed internally.
Note that you must not use val = ["world"], as this would again just assign a new list to val, but leave test unchanged, i.e. still refer to the old list containing "hello".

Python 3.8+ Tuple to variable index?

I have a variable, jdata, that holds data read from a JSON data file. It consists of many levels of dictionaries and lists of dictionaries. I have a search routine that returns a tuple containing path-like information to the element I want to access. I'm struggling to turn the tuple into a variable index. For example, the search routine may return ('name', 5, 'pic', 3). So I want to access jdata['name'][5]['pic'][3]. The number of levels down into the data can change for each search, so the tuple length is variable.
Addendum:
for everyone asking for code and what I've done:
I don't have code to share because I don't know how to do it and that's why I'm asking here. My first thought was to try and create the text for accessing the variable, for the example above,
"x = jdata['name'][5]['pic'][3]"
and then looking for a python way of executing that line of code. I figured there has to be a more elegant solution.
I thought the description of tuple to variable access was pretty straight forward, but here is an expanded version of my problem.
jdata = { 'thing1': 1,
'name': [
{},
{},
{},
{},
{},
{ 'thing11': 1,
'pic': [ 'LocationOfPicA',
'LocationOfPicB',
'LocationOfPicC',
'LocationOfPicD',
'LocationOfPicE'],
'thing12: 2},
{},
{} ],
'thing2': 2}
I searched for 'PicD' and my search code returns: ('name', 5, 'pic', 3)
Now I want to do some stuff, for example, accessing the value 'LocationOfPicD', copy the file located there to some other place, and update the value of 'LocationOfPicD' to the new value. All of this I can code. I just need to be able to turn the tuple into an accessible variable.
Edit: I was just reading about mutability in python. Instead of generating a path to an element in the dictionary, I think I can just assign that element value to a variable (x, for example) that gets passed back up the recursion chain of the initial search. From my understanding, I can change x and that also changes the element within the jdata variable. If that doesn't work, I can resort to using the eval() command on my generated text statement using the tuple as originally planned.
If I understand the problem correctly, you just need to avoid getting the lowest level item by value. So, you could do something like
indexes = ('name', 5, 'pic', 3)
x = jdata
for index in indexes[:-1]:
x = x[index]
x[indexes[-1]] = <new_value_here>
Easy and quick recursive implementation.
def get_d(d, tup, ind=0):
if ind == len(tup) - 1: # last item just return value
return d[tup[ind]]
return get_d(d[tup[ind]], tup, ind + 1) # else keep getting sub-item
# input input datastructure (could be dict, list, or gettable item) and tuple of items to recursively get
value = get_d(jdata, ('name', 5, 'pic', 3))
Note: this implementation is super basic and has no error handling. It's just here to give you an idea on how it could be done.

How to get all the iterations in a list with none values included from a tweet?

I have set of tweets with 10 dictionaries in the list "tweets". Each dictionary has several tweets. The first tweet has 100 and the rest 9 have 15 each.
I need the location of each tweet in all the dictionaries.
When I try to iterate the values from a list it shows this error.
if (type(tweets[j]['statuses'][k]['place']['name'])) != None:
TypeError: 'NoneType' object is not subscriptable
The code I have used for the iteration is
for j in range (0,10):
while j == 0:
for k in range(0,100):
st1 = tweets[j]['statuses'][k]['place']['name']
print(st1)
I tried using "filter" to take out the "None" values, even that is not working.
not every tweet has a location tagged to it. so it has None values. I need to print the locations of the tweets that are tagged.
Have you tried to check if the 'place' key is first available. I can see from your code that you are checking for ['place']['name']
Can you test your logic with the following filter logic without ['name']:
...
if (isinstance(tweets[j].get('statuses',[])[k].get('place', {}))) == dict:
...
The twitter api returns json, which is a dictionary type in Python. When you are calling keys using dict[key] syntax, this is called subscripting. Now, nested calls on a dict object are dependent on that object being a dictionary type:
dict[a][b] relies on dict[a] being a dictionary with key b being available. If dict[a] is a different type, say None or int, it is not subscriptable. This means that there is not necessarily a get attribute for that type. A simple way to fix this would be the following:
check = tweets[j]['statuses'][k]['place']
if isinstance(check, dict):
# do things
This makes sure that check is of type dict and therefore can be subscripted with a key
EDIT: Note that using dict[key] syntax is not safe against KeyErrors. If you want to avoid those, use get:
my_dictionary = {'a': 1, 'b': 2}
my_dictionary['c'] # Raises KeyError: 'c' not in dictionary
my_dictionary.get('c') # returns None, no KeyError
It takes the form dict.get(key, <return_value>), where return_value defaults to None
To make your program a bit more readable and avoid the inevitable infinite loop, ditch the while loop:
# This will get individual tweets
for tweet in tweets:
# Returns all statuses or empty list
statuses = tweet.get('statuses', [])
for status in statuses:
if not isinstance(status, dict):
continue # will jump to next iteration of inner for loop
# Will be a name or None, if empty dict is returned from place
name = status.get('place', {}).get('name')
if name:
print(name)
for element in tweets:
for s in element.get('statuses'):
place = s.get('place')
print(place['name'])
This fixed it.

Lookup for a key in dictionary with... regular expressions?

I have a dictionary that have the following structure: The key is a link between a source and a destination, the value is the instance of an object wire.
wire_dict = { source1_destination1_1 : object,
source1_destination1_2 : object
source2_destination1_3 : object
source2_destination1_4 : object
source2_destination2_1 : object
source2_destination2_2 : object }
Let's suppose that I only have a destination value, and with that I want to find, perhaps with regular expressions, the key that have the destination1_1. As you can see, same sources can have several destinations, but different sources cannot have the same destinations. So I want to find the key that ends with the destination.
Since the wire_dict could contain a lot of key-value entries, please tell me how this approach can affect the performance of the application. Perhaps I should create another dictionary only for the relationship between source and destination?
UPDATE: I change the dictionary with tuples as keys:
wire_dict = { ('source1','destination1_1') : object1,
('source1','destination1_2') : object2
('source2','destination1_3') : object3
('source2','destination1_4') : object4
('source2','destination2_1') : object5
('source2','destination2_2') : object6 }
The logic of the application is the same. A destination cannot have more than one source. So, only a coincidence should be found when a destination is provided.
Having string searches through dict keys is going to be linear time with standard python dictionaries. But it can be done with dict.keys() and re module as #avim helpfully told.
For the second concern, instead of string keys, how about having tuples as keys:
{(begin, end): connection_object}
It won't speed up at all (search is likely stay linear) but it enables better code behind the logic you want to express.
import re
wire_dict = {'source1_destination1_1' : 'object1',
'source1_destination1_2' : 'object2',
'source2_destination1_3' : 'object3',
'source2_destination1_4' : 'object4',
'source2_destination2_1' : 'object5',
'source2_destination2_2' : 'object6' }
pattern = 'source1_destination1_1'
print [value for key, value in wire_dict.items() if re.search(pattern, key)]
Output:
['object1']
It's easy to run over all dict keys and find the ones that match your pattern, but it's slow for big dicts.
I think you need another dict with keys matching your destinations (as you thought).
You just need str.endswith and to iterate over the dict checking each key.
print([k for k in wire_dict if k.endswith("destination1_1")])
If there is only over one use next and a generator expression:
k = next((k for k in wire_dict if k.endswith("destination1_1")),"")
If you want the value use wire_dict.get(k) in case there is no match and you get an empty string returned from the next call.
In [18]: k = next((k for k in wire_dict if k.endswith("destination1_1")),"")
In [19]: wire_dict[k]
Out[19]: object
In [20]: k
Out[20]: 'source1_destination1_1'
You should also never use dict.keys in python2 unless you actually want a list. You can simply iterate over the dict object to access each key efficiently.
Object oriented programming my friend
class Uberdict():
def init(source, destination, obj):
self.source, self.destination, self.obj = source, destination, obj
def has_destination(destination)
# True or False
return self.desination == destination
def has_source(source)
return self.source == source
wire_object_list = [
# list of the objects
]
# how to create them
example_obj = Uberdict(some_source, some_destination, some_instance)
wire_object_list.append(example_obj)
# filter
example_destination = 'some destination'
filtered_list = [item for item in wire_object_list if item.has_destination(example_destination)
only psuedo code could have errors

Python best way to create new dictionary looping through a list of dictionaries which contain lists

i have a PHP background and am fairly new to python, I am creating a helper class which is used to return some ldap results from an ldap server.
The standard result from pythons ldap library: ldap.search_s() is a list of tuples with dictionaries inside with lists inside ie:
[('uid', {'cn': ['cnvalue']}), ('uid2', {'cn': ['cnvalue2']})]
I would like to convert this into a simple list of dictionaries or in php talk an array of associative arrays.
For the life of me I cannot figure out how to do this.
This is how I have attempted it:
output = []
for i, result in enumerate(results):
d = {
'firstname': result[1].['givenName'][1],
'phone': result[1].['telephoneNumber'][1]
}
output.append(d)
return output
If telephoneNumber does not exist for an entry in ldap the python library does not populate that key, so some times I was running into invalid key exceptions, therefore I modified to the below.
output = []
for i, result in enumerate(results):
d = {
'firstname': result[1].get('givenName', '')[1],
'phone': result[1].get('telephoneNumber' ,'')[1]
}
output.append(d)
return output
Even so if a telephoneNumber does not exist then neither does the list entry [1], and so now I am running into "out of range" errors.
Help.
Thanks all.
result[1].get('givenName', '')
This will return either a list (if 'givenName' is a key in the dictionary whose value is a list) or an empty string (if 'givenName' is not a key).
You will then apply [1] to the result. Presumably you mean [0], but even so an empty string has length 0. You can't look up either index 0 or index 1 in it.
You could instead do:
result[1].get('givenName', [''])[0]
Now in the case where the key is missing you have a list containing an empty string. Therefore applying [0] to it gives you an empty string.
One alternative (which doesn't deal with an empty list, but I don't know whether or not that ever occurs in the data you're handling):
def getfirst(attrs, key):
list_or_none = attrs.get(key)
return '' if list_or_none is None else list_or_none[0]
Then:
d = {
'firstname': getfirst(result[1], 'givenName'),
}
Btw, you use enumerate but then never actually mention i. So you could just as well write for result in results:

Categories

Resources