Finding elements of a list and printing it out - python

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

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

How to convert for results into a list-Python

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']

How to do one liner "if" and "for-loop" together in python

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).

simplify expression in list comprehension

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.

Sorting a list using a regex in Python

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',))()

Categories

Resources