simplify expression in list comprehension - python

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.

Related

Python: Index slicing from a list for each index in for loop

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

Finding elements of a list and printing it out

i am still learning python and i am struggling to find a way to get this to work the way i want.
#First Method
staticPaths = [
"[N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-480]",
"[N4-OLDCLOUD-IPSTORAGE/epg-N4-NFS-NETAPP-8040-C01]/[vlan-481]]",
"['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-484]",
"['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-485]",
"['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C01-N2][vlan-480]"
]
for path in staticPaths:
filter_object = filter(lambda a: 'vlan-480' in a, staticPaths)
print(list(filter_object))
So what i am trying to do here is filter out anything that matches ‘vlan-480’ and return the entire line, so for example, if i run that code, i receive the correct output. which would be -
[N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C01-N2][vlan-480]
['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-480]
However where is states ‘vlan-480’ in the lambda function i actually want to pass it a LIST but because i am using the “in” statement, it only allows me to pass a single string.
Again i want to check multiples, so for example, give me the output for ‘vlan-480’ AND ‘vlan-484’ and it should return the lines for me from the staticPaths
I cannot think of way of getting this done, might just be me been stupid but for some reason i cannot solve it.
Also tried an if statement but i have the same problem, with the single string option.
#Second Method
path_matches = []
for path_match in staticPaths:
if 'vlan-480' in path_match:
path_matches.append(path_match)
print(path_matches)
Can anyone think of a way of doing this, its probably really easy but for some reason i cannot think of it. I did try and use List Comprehension but struggled to get the output i needed.
much appericated
Try this:
substrings = ['vlan-480', 'vlan-484']
filter_object = filter(lambda a: any(x in a for x in substrings), staticPaths)
print(list(filter_object))
The list substrings contains substrings to search for
The output I get for your dataset is:
['[N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-480]', "['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-484]", "['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C01-N2][vlan-480]"]
You can also use list comprehension
substrings = ['vlan-480', 'vlan-484']
path_matches = [x for x in staticPaths if substrings[0] in x or substrings[1] in x]
that results in :
path_matches
['[N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-480]',
"['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C02-N2][vlan-484]",
"['N4-NFS-NETAPP-8040-C01]/[N4-NHT-LEAF-VPC-FAS-C01-N2][vlan-480]"]
Your problem is with indentation i guess check this
path_matches = []
for path_match in staticPaths:
if 'vlan-480' in path_match:
path_matches.append(path_match)
Try to use this:
filter_object = filter(lambda a: 'vlan-480' in a or 'vlan-484' in a, staticPaths)
print(list(filter_object))
To do multi selection you can use operator OR/AND, so it will be such this 'vlan-480' in a or 'vlan-484' in a

Indexing a list in Python

I have a list of over 500s URLs that I have named in the following way:
url_1="https://www....."
url_2="https://www....."
url_3="https://www....."
and so on.
I am trying to put all of these URLs in a list, but I don't want to write the whole thing out. Is there a way to automatically generate an indexed list like this?
[url_1,url_2,url_3,...,url_500]
You can use list comprehension:
final_list = ["url_{}".format(i+1) for i in range(500)]
Output:
['url_1', 'url_2', 'url_3', 'url_4', 'url_5', 'url_6', 'url_7', 'url_8', 'url_9', 'url_10', 'url_11', 'url_12', 'url_13', 'url_14', 'url_15', 'url_16', 'url_17'...]
Or using the shorter, but less efficient, map function:
final_data = list(map(lambda x:"url_{}".format(x+1), range(500)))
Try this
['url_%s'%x for x in range(500)]

Finding the same second elements in nested lists - recursive function

I have nested lists looks like this;
[['CELTIC AMBASSASDOR', 'Warrenpoint'],['HAV SNAPPER', 'Silloth'],['BONAY', 'Antwerp'],['NINA', 'Antwerp'],['FRI SKIEN', 'Warrenpoint']]
and goes on. How can I find the lists that have same second elements, for example
['CELTIC AMBASSASDOR', 'Warrenpoint']
['FRI SKIEN', 'Warrenpoint']
['BONAY', 'Antwerp']
['NINA', 'Antwerp']
The list is too long (I'm reading it from a .csv file) and I can't determine to search which thing exactly (eg: I can't search for 'Antwerp' to find all Antwerps because I don't know all of the texts in csv file), so I thought I need a recursive function that will search until find the all nested lists seperated by second items. Couldn't figure out how to make the recursive function, if anyone has a better solution, much appreciated.
There's no need to use recursion here. Create a dictionary with a key of the second element and values of the whole sublist, then create a result that only includes the matches you're interested in:
import collections
l = [['CELTIC AMBASSASDOR', 'Warrenpoint'],['HAV SNAPPER', 'Silloth'],['BONAY', 'Antwerp'],['NINA', 'Antwerp'],['FRI SKIEN', 'Warrenpoint']]
d = collections.defaultdict(list)
for item in l:
d[item[1]].append(item)
result = dict(item for item in d.items() if len(d[item[0]]) > 1)
Result:
>>> import pprint
>>> pprint.pprint(result)
{'Antwerp': [['BONAY', 'Antwerp'], ['NINA', 'Antwerp']],
'Warrenpoint': [['CELTIC AMBASSASDOR', 'Warrenpoint'],
['FRI SKIEN', 'Warrenpoint']]}
filter(lambda x:x[1] in set(filter(lambda x:zip(*l)[1].count(x)==2,zip(*l)[1])),l)

Elegantly Generalising Sorting into Dictionaries in Python?

The list comprehension is a great structure for generalising working with lists in such a way that the creation of lists can be managed elegantly. Is there a similar tool for managing Dictionaries in Python?
I have the following functions:
# takes in 3 lists of lists and a column specification by which to group
def custom_groupby(atts, zmat, zmat2, col):
result = dict()
for i in range(0, len(atts)):
val = atts[i][col]
row = (atts[i], zmat[i], zmat2[i])
try:
result[val].append(row)
except KeyError:
result[val] = list()
result[val].append(row)
return result
# organises samples into dictionaries using the groupby
def organise_samples(attributes, z_matrix, original_z_matrix):
strucdict = custom_groupby(attributes, z_matrix, original_z_matrix, 'SecStruc')
strucfrontdict = dict()
for k, v in strucdict.iteritems():
strucfrontdict[k] = custom_groupby([x[0] for x in strucdict[k]],
[x[1] for x in strucdict[k]], [x[2] for x in strucdict[k]], 'Front')
samples = dict()
for k in strucfrontdict:
samples[k] = dict()
for k2 in strucfrontdict[k]:
samples[k][k2] = dict()
samples[k][k2] = custom_groupby([x[0] for x in strucfrontdict[k][k2]],
[x[1] for x in strucfrontdict[k][k2]], [x[2] for x in strucfrontdict[k][k2]], 'Back')
return samples
It seems like this is unwieldy. There being elegant ways to do almost everything in Python, I'm inclined to think I'm using Python wrongly.
More importantly, I'd like to be able to generalise this function better so that I can specify how many "layers" should be in the dictionary (without using several lambdas and approaching the problem in a Lisp style). I would like a function:
# organises samples into a dictionary by specified columns
# number of layers could also be assumed by number of criterion
def organise_samples(number_layers, list_of_strings_for_column_ids)
Is this possible to do in Python?
Thank you! Even if there isn't a way to do it elegantly in Python, any suggestions towards making the above code more elegant would be really appreciated.
::EDIT::
For context, the attributes object, z_matrix, and original_zmatrix are all lists of Numpy arrays.
Attributes might look like this:
Type,Num,Phi,Psi,SecStruc,Front,Back
11,181,-123.815,65.4652,2,3,19
11,203,148.581,-89.9584,1,4,1
11,181,-123.815,65.4652,2,3,19
11,203,148.581,-89.9584,1,4,1
11,137,-20.2349,-129.396,2,0,1
11,163,-34.75,-59.1221,0,1,9
The Z-matrices might both look like this:
CA-1, CA-2, CA-CB-1, CA-CB-2, N-CA-CB-SG-1, N-CA-CB-SG-2
-16.801, 28.993, -1.189, -0.515, 118.093, 74.4629
-24.918, 27.398, -0.706, 0.989, 112.854, -175.458
-1.01, 37.855, 0.462, 1.442, 108.323, -72.2786
61.369, 113.576, 0.355, -1.127, 111.217, -69.8672
Samples is a dict{num => dict {num => dict {num => tuple(attributes, z_matrix)}}}, having one row of the z-matrix.
The list comprehension is a great structure for generalising working with lists in such a way that the creation of lists can be managed elegantly. Is there a similar tool for managing Dictionaries in Python?
Have you tries using dictionary comprehensions?
see this great question about dictionary comperhansions

Categories

Resources