Hello i would like make list comprehension for two loops and return value from first loop. I have example:
rows = []
for row in value:
for pattern, sub_pattern in zip(pattern_tag, sub_pattern_list):
row = re.sub(pattern, sub_pattern, row)
rows.append(row)
how do I make a list, through list Comprehension, so that it gives the same result
This is probably not what you were looking for, but it's still a one-liner that makes use of the functools.reduce function:
from functools import reduce
from re import sub
rows = [
reduce(
lambda prev, curr: sub(*curr, prev),
zip(pattern_tag, sub_pattern_list),
row,
)
for row in value
]
To elaborate on Ricardo Bucco's answer and luk2302's comment.
List comprehensions create lists from other lists/iterables. Every item of "source" iterable either produces one item of resulting list or is skipped (if list comprehension has if clause). The order is preserved.
So your outer for loop can be converted to a list comprehension, since it constructs a list of replacements from a list of strings (presumably).
rows = [re.sub(..., ..., row) for row in value]
Inner for loop creates no list, and instead does a lot of subsequent replacements on a string, so it's not something that could be done using list comprehensions (hence _Riccardo_s' idea to use reduce()).
Related
Can someone explain why Python won't let me use i in this manner?
unit1 = [["cats allowed", True], ["bedrooms", 0], ["Balcony", False]]
userPref = []
for i in unit1:
userPref = userPref.append(unit1[i][1])
print(unit1[i][1])
I get this error message:
TypeError: list indices must be integers or slices, not list
If I want to iterate through the second item in each nested list, how would I go about doing that?
(FYI: the for loop in nested in an if statement. I omitted that for simplicity.)
Some options you have to iterate over a list:
1)
for item in unit1:
userPref.append(item[1])
print(item[1])
which item[1] is the second parameter of nested list
2)
for i in range(len(unit1)):
userPref.append(unit1[i][1])
print(unit1[i][1])
or if you need item and index together:
for i,item in enumerate(unit1):
userPref.append(item[1])
print(item[1])
for i in unit1:
When you iterate over a list in this way, i becomes each value in the list, not the list index.
So on the first iteration, i is the sub-list ["cats allowed", True].
If you want to iterate over the indexes of a list, use range():
for i in range(len(unit1)):
Python’s for statement iterates over the items of any sequence (a list or a string), in the order that they appear in the sequence.
You can found that differ in python official tutorial, the iteration will traverse all the value in the sequence rather index of that, which is quite different from other languages.
So I have a list of strings MyList=['ID_0','ID_1','ID_2',.....] from which I used an exec function to create a empty list with elements as names i.e. each I have empty lists ID_0=[] and so on.
I now want to create a for loop where I take each list by name and append elements to it like
for i in range(len(MyList)):
*magic*
ID_0.append(i)
where with each loop it uses to next list i.e. ID_1,ID_2.... and so on
I wanted to take each string in MyList and change it into a variable name. Like take 'ID_0' and change it into say ID_0 (which is a empty list as defined earlier) and then make a list BigList=[ID_0,ID_1,ID_2,.....] so that I can just call each list from BgList in my for loop but I dont know how
A safer way instead of using exec might be to construct a dictionary, so you can safely refer to each list by its ID:
MyList=['ID_0','ID_1','ID_2']
lists = {}
for i, list_id in enumerate(MyList):
lists[list_id] = [i]
Note that using enumerate is more pythonic than range(len(MyList)). It returns tuples of (index, item).
Alternatively, you could also use defaultdict, which constructs a new item in the dictionary the first time it is referenced:
from collections import defaultdict
lists = defaultdict(list)
for i, list_id in enumerate(MyList):
lists[list_id].append(i)
context: I have a list of lists and I am trying to get rid of duplicate entries. The list of lists is ordered by the first element in the sublist. When the function encounters the first occurrence of the sublist, the function appends that sublist to the "non_duplicate_list". If the function encounters another sublist with the same first element it continues.
Problem: I have a function that is working perfectly, but I feel it is too long. Is there any way to shorten/make the code more concise? maybe using list comprehension?
Here is the function:
def remove_duplicates(data_set):
non_duplicate_list = []
for row in data_set:
app_name = row[0]
if any(app_name in sublist for sublist in non_duplicate_list):
continue
else:
non_duplicate_list.append(row)
I tried doing this to make the function more concise, but it didn't work:
def remove_the_dupes(data_set):
non_duplicate_list = [continue if any(row[0] not in sublist for sublist in non_duplicate_list) else non_duplicate_list.append(row) for row in data_set]
return non_duplicate_list
I then get an error message about wrong syntax
please provide any shortened version of my function if possible. Many Thanks!
this should work
not_duplicate_list = [row for row in datset if not any(row[0] in sublist for sublist in non_duplicate_list)]
you shouldn't use continue and return in a list comprehension, take a look here for more info
I've got the list student:
student = ["test_name","1","6"]
And I've got the read data sublist:
read_data = [["test_name","1","2","5","9"],["test_name_2","1","5","2","10"]]
I've written the following nested loop to return the index of a sublist (referred to as x) in read_data if student[0] == x[0]:
lst = [read_data.index(x) for x in read_data if x[0] == student [0]]
So I'm looping through each item in read data and (if x[0] == student[0]) the index of the sublist should be stored in lst.
When I try to use this in the index parameter of a list to insert data like so:
read_data[read_data.index(x) for x in read_data if x[0] == student[0]].insert(2,student[0])
I get an error saying generators can't be used for indexes - why not?
I can obviously just use the integer stored in lst but this seems inefficient - surely there's a way to do this on one line.
Is there some better alternative method to checking if a string is in any of a read_data's sublists and getting the index of this sublist?
In the assignment to lst you are creating a list. But in the snippet below that, you have merely taken the interior of that list expression and are trying to use it as an index. To fix your specific example, you would need to change:
read_data[iter_expr]
to:
read_data[[iter_expr][0]]
That will use the first value in the list as the index.
There are better ways to do this, but this is probably the smallest change that will fix the specific problem you asked about.
I dont know why you would want to do this but then you need to put brackets around the list comprehension and get index the first match of it like this:
read_data[[read_data.index(x) for x in read_data if x[0] == student[0]][0]].insert(2, student[0])
Remember if the list comprehension produces an empty list, you will encounter an IndexError.
I have a dictionary where each value is a list, like so:
dictA = {1:['a','b','c'],2:['d','e']}
Unfortunately, I cannot change this structure to get around my problem
I want to gather all of the entries of the lists into one single list, as follows:
['a','b','c','d','e']
Additionally, I want to do this only once within an if-block. Since I only want to do it once, I do not want to store it to an intermediate variable, so naturally, a list comprehension is the way to go. But how? My first guess,
[dictA[key] for key in dictA.keys()]
yields,
[['a','b','c'],['d','e']]
which does not work because
'a' in [['a','b','c'],['d','e']]
yields False. Everything else I've tried has used some sort of illegal syntax.
How might I perform such a comprehension?
Loop over the returned list too (looping directly over a dictionary gives you keys as well):
[value for key in dictA for value in dictA[key]]
or more directly using dictA.itervalues():
[value for lst in dictA.itervalues() for value in lst]
List comprehensions let you nest loops; read the above loops as if they are nested in the same order:
for lst in dictA.itervalues():
for value in lst:
# append value to the output list
Or use itertools.chain.from_iterable():
from itertools import chain
list(chain.from_iterable(dictA.itervalues()))
The latter takes a sequence of sequences and lets you loop over them as if they were one big list. dictA.itervalues() gives you a sequence of lists, and chain() puts them together for list() to iterate over and build one big list out of them.
If all you are doing is testing for membership among all the values, then what you really want is to a simple way to loop over all the values, and testing your value against each until you find a match. The any() function together with a suitable generator expression does just that:
any('a' in lst for lst in dictA.itervalues())
This will return True as soon as any value in dictA has 'a' listed, and stop looping over .itervalues() early.
If you're actually checking for membership (your a in... example), you could rewrite it as:
if any('a' in val for val in dictA.itervalues()):
# do something
This saves having to flatten the list if that's not actually required.
In this particular case, you can just use a nested comprehension:
[value for key in dictA.keys() for value in dictA[key]]
But in general, if you've already figured out how to turn something into a nested list, you can flatten any nested iterable with chain.from_iterable:
itertools.chain.from_iterable(dictA[key] for key in dictA.keys())
This returns an iterator, not a list; if you need a list, just do it explicitly:
list(itertools.chain.from_iterable(dictA[key] for key in dictA.keys()))
As a side note, for key in dictA.keys() does the same thing as for key in dictA, except that in older versions of Python, it will waste time and memory making an extra list of the keys. As the documentation says, iter on a dict is the same as iterkeys.
So, in all of the versions above, it's better to just use in dictA instead.
In simple code just for understanding this might be helpful
ListA=[]
dictA = {1:['a','b','c'],2:['d','e']}
for keys in dictA:
for values in dictA[keys]:
ListA.append(values)
You can do some like ..
output_list = []
[ output_list.extend(x) for x in {1:['a','b','c'],2:['d','e']}.values()]
output_list will be ['a', 'b', 'c', 'd', 'e']