Python way to join subsets of an element into a string? - python

I have this code...it works, but is there a better way to do it?
So if the participant list is [ { 'Id': 5, 'name':'bob'}, {'Id': 4, 'name': 'sally'} ], result should be '5, 4'.
participant_list = obj['participants']
id_num = []
for participant in participant_list:
id_num.append(str(participant['Id']))
result = ",".join(id_num)

Use a list comprehension with str.join:
>>> participant_list = [ { 'Id': 5, 'name':'bob'}, {'Id': 4, 'name': 'sally'} ]
>>> ", ".join([str(p["Id"]) for p in participant_list])
'5, 4'
>>>

Using map(), This works -
>>> participant = [ { 'Id': 5, 'name':'bob'}, {'Id': 4, 'name': 'sally'} ]
>>> ",".join(map(lambda x: str(x['Id']), participant))
'5,4'

How about:
>>> ','.join([str(i['Id']) for i in participant_list])
'5,4'

Related

how to insert list of elements into list of dictionaries

I have one list of elements and another list of dictionaries and i want to insert list of elements into each dictionary of list
list_elem = [1,2,3]
dict_ele = [{"Name":"Madhu","Age":25},{"Name":"Raju","Age:24},{""Name":"Mani","Age":12}],
OUTPUT As:
[{"ID":1,"Name":"Madhu","Age":25},{"ID":2,"Name":"Raju","Age:24},{"ID":3,"Name":"Mani","Age":12}]
I have tried this way :
dit = [{"id":item[0]} for item in zip(sam)]
# [{"id":1,"id":2,"id":3}]
dic1 = list(zip(dit,data))
print(dic1)
# [({"id":1},{{"Name":"Madhu","Age":25}},{"id":2},{"Name":"Raju","Age:24},{"id":3},{""Name":"Mani","Age":12})]
What is the most efficient way to do this in Python?
Making an assumption here that the OP's original question has a typo in the definition of dict_ele and also that list_elem isn't really necessary.
dict_ele = [{"Name":"Madhu","Age":25},{"Name":"Raju","Age":24},{"Name":"Mani","Age":12}]
dit = [{'ID': id_, **d} for id_, d in enumerate(dict_ele, 1)]
print(dit)
Output:
[{'ID': 1, 'Name': 'Madhu', 'Age': 25}, {'ID': 2, 'Name': 'Raju', 'Age': 24}, {'ID': 3, 'Name': 'Mani', 'Age': 12}]
dict_ele = [{"Name":"Madhu","Age":25},{"Name":"Raju","Age":24},{"Name":"Mani","Age":12}]
list_elem = [1,2,3]
[{'ID': id, **_dict} for id, _dict in zip(list_elem, dict_ele)]
[{'ID': 1, 'Name': 'Madhu', 'Age': 25}, {'ID': 2, 'Name': 'Raju', 'Age': 24}, {'ID': 3, 'Name': 'Mani', 'Age': 12}]
try this: r = [{'id':e[0], **e[1]} for e in zip(list_elem, dict_ele)]

Python str not list

I wanted to obtain array of int like [1,2,3]
but got [dict_values([1]),dict_values([2]),dict_values([3])]
My code:
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
taken_employee_ids = [str(taken_employee_ids_list.values()) for taken_employee_ids_list in taken_employee_ids_dict]
in_values_check = ','.join(str(id) for id in taken_employee_ids)
And then in_values_check should go in:
qry = "SELECT CONCAT(first_name, ',', surname) AS full_name, id \
FROM employees \
WHERE date_terminated IS NULL \
and id NOT IN " + "(" + in_values_check + ")" \
" ORDER BY first_name, surname ASC"
sorry i am new to python thanks
For a problem like this, a list comprehension is a commonly applied solution:
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
in_values_check = [employee["id"] for employee in taken_employee_ids_dict]
print(in_values_check)
This outputs
[1, 2, 3]
You can do it with lambda or list comprehension
With Lambda,
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
in_values_check = list(map(lambda x : x['id'], taken_employee_ids_dict))
print(in_values_check)
With List Comprehension,
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
in_values_check = [dic['id'] for dic in taken_employee_ids_dict]
print(in_values_check)
Output:
[1, 2, 3]
You can use something like this.
taken_employee_ids_dict = [{'id': 1}, {'id': 2}, {'id': 3}]
final_list = []
for ele in taken_employee_ids_dict:
for key,value in ele.items():
final_list.append(value)
print(final_list)
Try this:
taken_employee_ids = [str(employee["id"]) for employee in taken_employee_ids_dict]
in_values_check = ','.join(str(id) for id in taken_employee_ids)

creating a list of dictionary in python

from the given input
lists = ["7ee57f24", "deadbeef"]
I want to get the following output
l1': [
{
'd':
{
'id': '7ee57f24'
}
},
{
'd':
{
'id': 'deadbeed'
}
}
]
I have tried this code
lists = ["7ee57f24", "deadbeef"]
l1 = {"d":[{"id": lis} for lis in lists]}
print(l1)
but it gives me wrong output
{'d': [{'id': '7ee57f24'}, {'id': 'deadbeef'}]}
Use the following:
lists = ["7ee57f24", "deadbeef"]
l1 = [
{"d": {"id": id_}}
for id_ in lists
]
print(l1)
Output:
[{'d': {'id': '7ee57f24'}}, {'d': {'id': 'deadbeef'}}]

Dealing with duplicates in lists of dictionaries

I uploaded a a csv file using DictReader so I essentially have a list of dictionaries. For example I have a called reader with the following:
[{'name': 'Jack', 'hits:' :7, 'misses:': 12, 'year': 10},
{'name': 'Lisa', 'hits': 5, 'misses': 3,' year': 8},
{'name': 'Jack', 'hits': 5, 'misses ':7, 'year': 9}]
I am using a loop to create lists like the following:
name = []
hits = []
for row in reader:
name.append(row["name"])
hits.append(row["hits"])
However I don't want duplicates in my list so where there is a duplicate name I am only interested in the names with the highest year. So basically I want to end up with the following
name = [Jack, Lisa]
hits = [7,5]
What is the best way to go about this
TRY:
reader = sorted(reader, key = lambda i: i['year'], reverse=True)
name = []
hits = []
for row in reader:
if row['name'] in name:
continue
name.append(row["name"])
hits.append(row["hits"])
Idea is to sort the list of dict based on year and then iterate over the list.
import pandas as pd
data = [{'name': 'Jack', 'hits' :7, 'misses': 12, 'year': 10},
{'name': 'Lisa', 'hits': 5, 'misses': 3,'year': 8},
{'name': 'Jack', 'hits': 5, 'misses':7, 'year': 9}]
df = pd.DataFrame(data).sort_values(by=['name','year'],ascending=False).groupby('name').first()
dict(zip(df.index,df['hits']))
In pure Python (no libraries):
people = {} # maps "name" -> "info"
for record in csv_reader:
# do we have someone with that name already?
old_record = people.get(record['name'], {})
# what's their year (defaulting to -1)
old_year = old_record.get('year', -1)
# if this record is more up to date
if record['year'] > old_year:
# replace the old record
people[record['name']] = record
# -- then, you can pull out your name and year lists
name = list(people.keys())
year = list(r['year'] for r in people.values())
If you want to learn Pandas
import pandas as pd
df = pd.read_csv('yourdata.csv')
df.groupby(['name']).max()
Solution without pandas:
lst = [
{"name": "Jack", "hits": 7, "misses:": 12, "year": 10},
{"name": "Lisa", "hits": 5, "misses": 3, " year": 8},
{"name": "Jack", "hits": 5, "misses ": 7, "year": 9},
]
out = {}
for d in lst:
out.setdefault(d["name"], []).append(d)
name = [*out]
hits = [max(i["hits"] for i in v) for v in out.values()]
print(name)
print(hits)
Prints:
['Jack', 'Lisa']
[7, 5]

How to apply a function to a sequence of dicts?

I have the following function:
def count_chars(e):
return len(e)
I am iterating a json as follows:
In:
a_lis = []
with open('../JSON_FILE.json','r') as fa:
a = json.load(fa)
for e in a['entries']:
pprint(e)
Out:
{'data': ['string'], 'type': 'one'}
{'data': ['a string '], 'type': 'one'}
{'data': ['another string'], 'type': 'three'}
...
{'data': ['one more string'], 'type': 'two'}
How can I apply count_chars function and add it or update it as a new string in the 'data' list? For instance the expected output would look like:
{'data': ['string','6'], 'type': 'one'}
{'data': ['a string','8'], 'type': 'one'}
{'data': ['another string','14'], 'type': 'three'}
...
{'data': ['one more string','15'], 'type': 'two'}
UPDATE:
I found that my lists have more than one item, for example: ['first', 'second string']? How can I return ['first', len_1, 'second string', len_2]
You could use append():
lst = [
{"data": ["string"], "type": "one"},
{"data": ["a string "], "type": "one"},
{"data": ["another string"], "type": "three"},
]
def count_chars(e):
return len(e)
for d in lst:
d["data"].append(count_chars(d["data"][0]))
print(lst)
# [{'data': ['string', 6], 'type': 'one'}, {'data': ['a string ', 9], 'type': 'one'}, {'data': ['another string', 14], 'type': 'three'}]
If you have more strings in the list, you can use extend() and rebuild a new list:
lst = [
{"data": ["string", "hi"], "type": "one"},
{"data": ["a string "], "type": "one"},
{"data": ["another string"], "type": "three"},
]
def count_chars(e):
return len(e)
for d in lst:
newlst = []
for x in d["data"]:
newlst.extend([x, count_chars(x)])
d["data"] = newlst
print(lst)
# [{'data': ['string', 6, 'hi', 2], 'type': 'one'}, {'data': ['a string ', 9], 'type': 'one'}, {'data': ['another string', 14], 'type': 'three'}]
Note: Since count_chars() simply returns len(), it might be easier to just call len() itself.
That should work :)
def count_chars(e):
return len(e)
a_lis = []
with open('../JSON_FILE.json','r') as fa:
a = json.load(fa)
for e in a['entries']:
for String in e["data"]: # Grab one string inside the strings list.
if type(String) == int:
continue # Skip the count chars value that you appended.
Length = count_chars(String) # Apply the function.
e["data"].append(Length) # Append the returned value to the data list containing the string.
# Now we reorder the list from ["a", "ab", "abc", 1, 2, 3] to ["a", 1, "ab", 2, "abc", 3]
strings_found = int(len(e["data"])/2)
reordered_list = []
for start in range(0, strings):
reordered_list = reordered_list + [x for x in e["data"][start::strings_found ]]
e["data"] = reordered_list

Categories