I got stuck in slicing from a list of data inside a for loop.
list = ['[init.svc.logd]: [running]', '[init.svc.logd-reinit]: [stopped]']
what I am looking for is to print only key without it values (running/stopped)
Overall code,
for each in list:
print(each[:]) #not really sure what may work here
result expected:
init.svc.logd
anyone for a quick solution?
If you want print only the key, you could use the split function to take whatever is before : and then replace [ and ] with nothing if you don't want them:
list = ['[init.svc.logd]: [running]', '[init.svc.logd-reinit]: [stopped]']
for each in list:
print(each.split(":")[0].replace('[','').replace(']','')) #not really sure what may work here
which gives :
init.svc.logd
init.svc.logd-reinit
You should probably be using a regular expression. The concept of 'key' in the question is ambiguous as there are no data constructs shown that have keys - it's merely a list of strings. So...
import re
list_ = ['[init.svc.logd]: [running]', '[init.svc.logd-reinit]: [stopped]']
for e in list_:
if r := re.findall('\[(.*?)\]', e):
print(r[0])
Output:
init.svc.logd
init.svc.logd-reinit
Note:
This is more robust than string splitting solutions for cases where data are unexpectedly malformed
I am trying to put my results into a list.
Here is my code:
from ise import ERS
l = ise.get_endpoints(groupID=my_group_id)['response']
Here is my output:
[('AA:BB:CD', 'cvr5667'), ('AA:BB:CC', '8888')]
Here is my desired output which is a list of just the first elements of inside the parentheses:
['AA:BB:CD','AA:BB:CC']
I am new at python and working with lists/dicts so any suggestions would. All I am trying to do it put the first elements inside the parentheses in one list like i showed.
Using list comprehension (as suggested in comments too):
lst_1 = [('AA:BB:CD', 'cvr5667'), ('AA:BB:CC', '8888')]
lst_result = [i[0] for i in lst_1]
With something like this ?
result = [('AA:BB:CD', 'cvr5667'), ('AA:BB:CC', '8888')]
first_elements_to_list = [tmp[0] for tmp in result]
print(first_elements_to_list)
print:
['AA:BB:CD', 'AA:BB:CC']
So I have been liking to have my code more clean and I have been stuck into something that might be very easy to do.
Basically what I have done is currently:
for raw_product in r.json().get('data'):
if raw_product.get('countdown') is False:
print(raw_product.get('url'))
and I have been trying to figure out how to make it to one liner. So far I have only come to
test = ['{}'.format(raw_product.get('url')) for raw_product in r.json().get('data')]
however inside the one liner, there is missing the if statement and I wonder if it possible to apply the if statement inside the ['{}'.format(raw_product.get('url')) for raw_product in r.json().get('data')] ?
Try this generator :
gen = (repr(x.get('url')) for x in r.json().get('data') if not x.get('countdown'))
Or list :
li = [repr(x.get('url')) for x in r.json().get('data') if not x.get('countdown')]
What makes thise code not clean, is not the comprehension, but this
'get' methods. Compare that to :
li = [x.url for x in r.json_data if not x.countdown]. Is kind of clearer.
I'm not sure it's cleaner, but you can use a generator expression with an if filter to get this kind of pattern in one line:
[ print(rp.get('url')) for rp in r.json().get('data') if rp.get('countdown') is False ]
Note that this has the inefficiency of creating and remembering a whole list of None values (the result of every print call).
I am trying to generate a list of strings, and I am looking for a simple expression to do so but can't find out.
What I have:
aScanListNames = ["AIN0", "AIN1", "AIN2", "AIN3"]
[[chan+"_NEGATIVE_CH", chan+"_RANGE", chan+"_RESOLUTION_INDEX", chan+"_EF_CONFIG_D", chan+"_EF_CONFIG_E"] for chan in aScanListNames]
Gives :
[['AIN0_NEGATIVE_CH', 'AIN0_RANGE', 'AIN0_RESOLUTION_INDEX', 'AIN0_EF_CONFIG_D', 'AIN0_EF_CONFIG_E'], ['AIN1_NEGATIVE_CH', 'AIN1_RANGE', 'AIN1_RESOLUTION_INDEX', 'AIN1_EF_CONFIG_D', 'AIN1_EF_CONFIG_E'], ['AIN2_NEGATIVE_CH', 'AIN2_RANGE', 'AIN2_RESOLUTION_INDEX', 'AIN2_EF_CONFIG_D', 'AIN2_EF_CONFIG_E'], ['AIN3_NEGATIVE_CH', 'AIN3_RANGE', 'AIN3_RESOLUTION_INDEX', 'AIN3_EF_CONFIG_D', 'AIN3_EF_CONFIG_E']]
which is , as expected, a list of lists. I would like to obtain a simple list, like this :
['AIN0_NEGATIVE_CH','AIN0_RANGE','AIN0_RESOLUTION_INDEX','AIN0_EF_CONFIG_D','AIN0_EF_CONFIG_E','AIN1_NEGATIVE_CH','AIN1_RANGE','AIN1_RESOLUTION_INDEX','AIN1_EF_CONFIG_D','AIN1_EF_CONFIG_E','AIN2_NEGATIVE_CH','AIN2_RANGE','AIN2_RESOLUTION_INDEX','AIN2_EF_CONFIG_D','AIN2_EF_CONFIG_E','AIN3_NEGATIVE_CH','AIN3_RANGE','AIN3_RESOLUTION_INDEX','AIN3_EF_CONFIG_D','AIN3_EF_CONFIG_E']
For my personnal knowledge, I would like to know if there a way to obtain this directly using list comprehension?
If not, what would be a pythonic way to do so?
EDIT: I know I can flatten my list of list, but I want to know if there is a solution not involving creating a list of lists to flatten it after.
You were almost there. No need for itertools
aScanListNames = ["AIN0", "AIN1", "AIN2", "AIN3"]
suffixes = ["_NEGATIVE_CH", "_RANGE", "_RESOLUTION_INDEX", "_EF_CONFIG_D", "_EF_CONFIG_E"]
result = [name+suffix for name in aScanListNames for suffix in suffixes]
I would say this one-liner is intuitive enough:
import itertools
aScanListNames = ["AIN0", "AIN1", "AIN2", "AIN3"]
suffixes = ["_NEGATIVE_CH", "_RANGE", "_RESOLUTION_INDEX", "_EF_CONFIG_D", "_EF_CONFIG_E"]
[i[0] + i[1] for i in itertools.product(aScanListNames, suffixes)]
Output:
['AIN0_NEGATIVE_CH', 'AIN0_RANGE', 'AIN0_RESOLUTION_INDEX', 'AIN0_EF_CONFIG_D', 'AIN0_EF_CONFIG_E', 'AIN1_NEGATIVE_CH', 'AIN1_RANGE', 'AIN1_RESOLUTION_INDEX', 'AIN1_EF_CONFIG_D', 'AIN1_EF_CONFIG_E', 'AIN2_NEGATIVE_CH', 'AIN2_RANGE', 'AIN2_RESOLUTION_INDEX', 'AIN2_EF_CONFIG_D', 'AIN2_EF_CONFIG_E', 'AIN3_NEGATIVE_CH', 'AIN3_RANGE', 'AIN3_RESOLUTION_INDEX', 'AIN3_EF_CONFIG_D', 'AIN3_EF_CONFIG_E']
If you really want a one-liner you can of course provide suffixes list inline, but that's just messy.
I have a list of email addresses with the following format:
name####email.com
But the number is not always present. For example: john45#email.com, bob#email.com joe2#email.com, etc. I want to sort these names by the number, with those without a number coming first. I have come up with something that works, but being new to Python, I'm curious as to whether there's a better way of doing it. Here is my solution:
import re
def sortKey(name):
m = re.search(r'(\d+)#', name)
return int(m.expand(r'\1')) if m is not None else 0
names = [ ... a list of emails ... ]
for name in sorted(names, key = sortKey):
print name
This is the only time in my script that I am ever using "sortKey", so I would prefer it to be a lambda function, but I'm not sure how to do that. I know this will work:
for name in sorted(names, key = lambda n: int(re.search(r'(\d+)#', n).expand(r'\1')) if re.search(r'(\d+)#', n) is not None else 0):
print name
But I don't think I should need to call re.search twice to do this. What is the most elegant way of doing this in Python?
Better using re.findall as if no numbers are found, then it returns an empty list which will sort before a populated list. The key used to sort is any numbers found (converted to ints), followed by the string itself...
emails = 'john45#email.com bob#email.com joe2#email.com'.split()
import re
print sorted(emails, key=lambda L: (map(int, re.findall('(\d+)#', L)), L))
# ['bob#email.com', 'joe2#email.com', 'john45#email.com']
And using john1 instead the output is: ['bob#email.com', 'john1#email.com', 'joe2#email.com'] which shows that although lexicographically after joe, the number has been taken into account first shifting john ahead.
There is a somewhat hackish way if you wanted to keep your existing method of using re.search in a one-liner (but yuck):
getattr(re.search('(\d+)#', s), 'groups', lambda: ('0',))()