Python - variable as list index - python

I'm wondering if this is possible in python.
I'm accessing a list in this way:
print list[0]['name']
This is fine. Is there a way to use a variable?
I mean:
a="[0]['name']"
print list[a]
Thanks for your suggestions.
Some details:
I have a situation where I have something like this:
a = [{"name":"someone", "age":23}]
print a[0]['name']
But since I need to pass "[0]['name']" as parameter, I'd like to understand if this is possible.
Thanks,
cips

This is a simple matter of extracting the indices/keys from the string "[0]['name']" and then using those keys to index the list/dict structure.
data = [{"name":"someone", "age":23}]
keys = "[0]['name']"
# split the string into a list of indices/keys
keys = keys[1:-1].split('][')
# keys = ['0', "'name'"]
# the keys are all strings, so we have to convert
# each individual key to the correct type
import ast
keys = [ast.literal_eval(key) for key in keys]
# keys = [0, 'name']
# now use the list of indices/keys we generated to get the value
value = data
for key in keys:
value = value[key]
print(value) # output: someone

I hope not to be out of context, but maybe you can use a function like this if you can
convert s = "[0]['name']" to s = (0, 'name'):
def search_index(obj, itero):
try:
return search_index(obj[next(itero)], itero)
except StopIteration:
return obj
a = [{"name":"someone", "age":23}]
s = (0, 'name')
result = search_index(a, iter(s))
# >>> result = 'someone'
If you want to convert "[0]['name']" to (0, 'name') you can try this:
import re
reg = re.findall(r'\[(\d*?)\]|\[\'(\w*?)\'\]', "[0]['name']")
s = [int(index[0]) if not index[1] else index[1] for index in reg]
# [0, 'name']
It will convert the indexes to the right type, to work with either list or dicts.

In general it is dangerous to use eval but you essentially need to convert your string to perform your indexing.
So first you can get your list as a str using repr
>>> l = [{'name': 'bob'}]
>>> repr(l)
"[{'name': 'bob'}]"
then if you concatenate that with your index operation
>>> a = "[0]['name']"
>>> repr(l) + a
"[{'name': 'bob'}][0]['name']"
then eval the whole thing, it should do the trick
>>> eval(repr(l) + a)
'bob'

you can use the function eval('a[0][name]'), it will evaluate the string inside as a python code.
here is the reference:
https://docs.python.org/3/library/functions.html#eval

You can use exec command
exec("print(list{})".format(a))
I hope it works

Related

How to change the index of an element in a list/array to another position/index without deleting/changing the original element and its value

For example lets say I have a list as below,
list = ['list4','this1','my3','is2'] or [1,6,'one','six']
So now I want to change the index of each element to match the number or make sense as I see fit (needn't be number) like so, (basically change the index of the element to wherever I want)
list = ['this1','is2','my3','list4'] or ['one',1,'six',6]
how do I do this whether there be numbers or not ?
Please help, Thanks in advance.
If you don't wanna use regex and learn it's mini language use this simpler method:
list1 = ['list4','this1', 'he5re', 'my3','is2']
def mySort(string):
if any(char.isdigit() for char in string): #Check if theres a number in the string
return [float(char) for char in string if char.isdigit()][0] #Return list of numbers, and return the first one (we are expecting only one number in the string)
list1.sort(key = mySort)
print(list1)
Inspired by this answer: https://stackoverflow.com/a/4289557/11101156
For the first one, it is easy:
>>> lst = ['list4','this1','my3','is2']
>>> lst = sorted(lst, key=lambda x:int(x[-1]))
>>> lst
['this1', 'is2', 'my3', 'list4']
But this assumes each item is string, and the last character of each item is numeric. Also it works as long as the numeric parts in each item is single digit. Otherwise it breaks. For the second one, you need to define "how you see it fit", in order to sort it in a logic.
If there are multiple numeric characters:
>>> import re
>>> lst = ['lis22t4','th2is21','my3','is2']
>>> sorted(lst, key=lambda x:int(re.search(r'\d+$', x).group(0)))
['is2', 'my3', 'list4', 'this21']
# or,
>>> ['is2', 'my3', 'lis22t4', 'th2is21']
But you can always do:
>>> lst = [1,6,'one','six']
>>> lst = [lst[2], lst[0], lst[3], lst[1]]
>>> lst
['one', 1, 'six', 6]
Also, don't use python built-ins as variable names. list is a bad variable name.
If you just want to move element in position 'y' to position 'x' of a list, you can try this one-liner, using pop and insert:
lst.insert(x, lst.pop(y))
If you know the order how you want to change indexes you can write simple code:
old_list= ['list4','this1','my3','is2']
order = [1, 3, 2, 0]
new_list = [old_list[idx] for idx in order]
If you can write your logic as a function, you can use sorted() and pass your function name as a key:
old_list= ['list4','this1','my3','is2']
def extract_number(string):
digits = ''.join([c for c in string if c.isdigit()])
return int(digits)
new_list = sorted(old_list, key = extract_number)
This case list is sorted by number, which is constructed by combining digits found in a string.
a = [1,2,3,4]
def rep(s, l, ab):
id = l.index(s)
q = s
del(l[id])
l.insert(ab, q)
return l
l = rep(a[0], a, 2)
print(l)
Hope you like this
Its much simpler

How to parse Python set-inside-list structure into text?

I have the following strange format I am trying to parse.
The data structure I am trying to parse is a "set" of key-value pairs in a list:
[{'key1:value1', 'key2:value2', 'key3:value3',...}]
That's the only data I have, and it needs to be processed. I don't think this can be described as a Python data structure, but I need to parse this to become a string like
'key1:value1, key2:value2, key3:value3'.
Is this doable?
EDIT: Yes, it is key:value, not key:value
Also, this is Python3.x
Iterating over .items() and formatting differently then previous answers.
If your data is the following: list of dict objects then
>>> data = [{'key1':'value1', 'key2':'value2', 'key3':'value3'}]
>>> ', '.join('{0}:{1}'.format(*item) for item in my_dict.items() for my_dict in data)
'key2:value2, key3:value3, key1:value1'
If you data is the list of set objects then approach is simpler
>>> from itertools import chain
>>> data = [{'key1:value1', 'key2:value2', 'key3:value3'}]
>>> ', '.join(chain.from_iterable(data))
'key1:value1, key2:value2, key3:value3'
UPD
NOTE: order can be changed, because set and dict objects are not ordered.
', '.join('{0}:{1}'.format(key, value) for key, value in my_dict.iteritems() for my_dict in my_list)
where my_list is name of your list variable
Since your structure (let's call it myStruct) is a set rather than a dict, the following code should do what you want:
result = ", ".join([x for x in myStruct[0]])
Beware, a set is not ordered, so you might end up with something like 'key2:value2, key1:value1, key3:value3'.
I would use itertools
d = {'key1':'value1', 'key2':'value2', 'key3':'value3'}
for k, v in d.iteritems():
print k + v + ',',
So, you have a list whose only element is a dictionary, and you want to get all the keys-value pairs from that dictionary and put them into a string?
If so, try something like this:
d = yourList[0]
s = ""
for key in d.keys():
s += key + ":" + d[key] + ", "
s = s[:-2] #To trim off the last comma that gets added
Try this,
print ', '.join(i for x in list_of_set for i in x)
If it's set there is no issue with the parsing. The code is equals to
output = ''
for x in list of_set:
for i in x:
output += i
print output

How to get dictionary in python list matching a given criteria

I have list of dictionaries-
[{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
I want to get the dictionary where id = 1 and store it in a variable.Something like-
element = {"id":1,"name":"abc"}
I don't want to use for loop to iterate through the list and then fetch the element.
No matter what you do, you'll have to iterate over that list.
g = (e for e in elements if e.get('id') == 1)
element = next(g)
The nice thing about this implementation is it only iterates as much as needed to find the next matching element.
The problem you are addressing is called indexing. If you don't know anything about your matching criterias a priori then there is nothing you can do and you have to do the loop. The easiest implementation would be:
my_obj = next(obj for obj in my_list if my_criterium(obj))
where in your case
my_criterium = lambda obj: obj['id'] == 1
However if you know that you will always search by id then you can create an index:
my_index = {obj['id']: obj for obj in my_list}
Then the retrieveing is as simple as
my_obj = my_index[1]
which no longer requires a loop (and thus is fast).
This is under assumption that id is unique on each object (this assumption is not crutial, you can create a different index by storing a list of matched element for each id). The other drawback is that it will be hard to keep both the index and the list consistent between each other.
But no matter what path you chose there is no escape from a loop.
Dicts = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
for d in Dicts:
if d.get('id') == 1:
element = d
print element
You can store the ids of your dictionary-list into another dictionary using just one for loop. This will be much faster when you have multiple queries.
In [1]: d = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
In [2]: indices = {v["id"] : index for index, v in enumerate(d)}
In [3]: element = d[indices[1]]
In [4]: print(element)
{'id': 1, 'name': 'abc'}
In [5]: element = d[indices[3]]
In [6]: print(element)
{'id': 3, 'name': 'xyz'}
I think I have a solution.
Basically, you convert the list into a string and then you play with it to make a single dictionary.
Although, I think that looping over the list is way better.
l = [{"id":1,"name":"abc"},{"id":2,"name":"def"},{"id":3,"name":"xyz"}]
#convert to string
a = str(l)
#remove parenthesis and curly brackets
a = a.replace('{','').replace('}','').replace('[','').replace(']','').replace(' ','')
#remove 'id' and 'name'
a = a.replace("'id':",'').replace(",'name'",'')
#add curly brackets
a = '{'+a+'}'
#make a dict
exec('a='+a)
>>>a
{1: 'abc', 2: 'def', 3: 'xyz'}
As you can see, you end up with a single dictionary with the right key/value pairs without using a single for loop!

How to make sets of iterators

I want to iterate over a certain range and create several sets that contain only the current i. (In the code I don't want to do this for every i, but it's about the general principle).
for i in range(5):
s=set(i)
print(s)
It says int object is not iterable. Why doesn't this work? Please keep the answers simple, I'm a newbie.
set() takes a sequence of values to add, and a single integer is not a sequence.
You could wrap it in a tuple or a list:
s = set((i,))
s = set([i])
but the better option is to use the {..} set literal notation:
s = {i}
The notation looks a lot like creating a dictionary, but you only list values, not keys.
Demo (on Python 2, where the representation uses set([..]) notation):
>>> i = 42
>>> set((i,))
set([42])
>>> set([i])
set([42])
>>> {i}
set([42])
Python 3 reflects sets using the literal notation:
>>> i = 42
>>> {i}
{42}
Set constructor set(x) requires x to be some container, like a list, or other set. You pass an integer, python tries to iterate over it, and fails.
In order to do so you need to pass a singleton of x, like that:
for i in range(5):
s = set([i]) # or s = set((i,))
print(s)
or through simplified set constructor
for i in range(5):
s = {i}
print(s)
or construct an empty set and add your element
for i in range(5):
s = set()
s.add(i)
print(s)
instead of using a for loop in range, you can also feed it to set (or a frozenset if you dont need to change it's content):
>>> set(range(5))
# {0, 1, 2, 3, 4}

Convert list to string using python

I have the list it contain int ,float and string:
lists = [10, "test", 10.5]
How Can i convert above list to string? I have tried:
val = ','.join(lists)
print val
I am getting error like this:
sequence item 0: expected string, int found
How can I solve this issue?
Firstly convert integers to string using strusing map function then use join function-
>>> ','.join(map(str,[10,"test",10.5]) )#since added comma inside the single quote output will be comma(,) separated
>>> '10,test,10.5'
Or if you want to convert each element of list into string then try-
>>> map(str,[10,"test",10.5])
>>> ['10', 'test', '10.5']
Or use itertools for memory efficiency(large data)
>>>from itertools import imap
>>>[i for i in imap(str,[10,"test",10.5])]
>>>['10', 'test', '10.5']
Or simply use list comprehension
>>>my_list=['10', 'test', 10.5]
>>>my_string_list=[str(i) for i in my_list]
>>>my_string_list
>>>['10', 'test', '10.5']
The easiest way is to send the whole thing to str() or repr():
>>> lists = [10, "test", 10.5]
>>> str(lists)
"[10, 'test', 10.5]"
repr() may produce a different result from str() depending on what's defined for each type of object in the list. The point of repr() is that you can send such strings back to eval() or ast.literal_eval() to get the original object back:
>>> import ast
>>> lists = [10, "test", 10.5]
>>> ast.literal_eval(repr(lists))
[10, 'test', 10.5]
a = ['b','c','d']
strng = ''
for i in a:
strng +=str(i)
print strng
The error you are getting because join wants elements to be string type, but in your list there is integer too, so 1st you have to convert them to type string.
you can use list comprehension and str and join to join them
>>> lists = [10,"test",10.5]
>>> ",".join(str(x) for x in lists)
You have to pass each item in your list as a string into the ','.join(sequence). Consider using:
val = ','.join([str(item) for item in lists])
print val
If you want to convert each element in the list to a string, you could do it simply using a for-loop.
for i in range(len(lists)):
lists[i] = str(lists[i])
Alternatively, if you want to make one string where all elements are joined together, you could edit the code above slightly.
string_of_lists = ""
for i in lists:
string_of_lists += str(i)
As you can tell, this is another way of doing it, apart from the other solutions using join.
I hope I helped!
This is also possible. Here x variable is list.
>>> '%s'*len(x) % tuple(x)
As mentioned here
list=['a/b/c', 'd/e/f']
file_list_string= ' '.join(list)
file_list_string= ' '.join(str(file) for file in list)
import functools
lists = [10,"test",10.5]
print(functools.reduce(lambda x,y:x+","+y,list(map(str,lists))))
You could always do it the dirty way:
list_name = ["a", "b", "c"];
string_name = "";
for c in list_name:
string_name += c
print(string_name)
OUTPUT:
"abc"
That should work with ints, floats, and strings, always converting them to string type.

Categories

Resources