some_list = ['Name','Surname','R500']
some_list = ['Name','Surname','500']
how would if get the index of the item in the list that contains a number, in both cases I should get back index = 2
I was looking at something like:
some_list.index(r'%r' % '\d+')
You'll need to loop over the elements:
for i, x in enumerate(my_list):
if re.search(r"\d", x):
print i
If you're looking just for the first item containing a digit, this works without regular expressions and returns -1 (can be changed to whatever you want) if there is no element with digits:
next((i for i,n in enumerate(some_list) if any(c.isdigit() for c in n)), -1)
Related
What I have here is hard to read and I was wondering how I could write this in fewer lines of code.
lst = [-3,10.5,100]
def add_index(nums):
lst2=[]
add = 0
for i in nums:
add += 1
lst2.append(i+add)
return lst2
add_index(lst)
For each iteration of your loop, add contains a 1-based index and i contains the corresponding list item. There’s a built-in Python function called enumerate that yields each item from an iterable along with its index as an (index, item) tuple.
Example of its use with your loop:
lst2 = []
for i, x in enumerate(nums, start=1):
lst2.append(x + i)
return lst2
which leads to a list comprehension equivalent:
def add_index(nums):
return [x + i for i, x in enumerate(nums, start=1)]
you can use enumerate with an initial value of 1 to pair the list's numbers with the value to add and map the sum function to perform the addition on each pair:
def add_index(nums): return [*map(sum,enumerate(nums,1))]
Of do the addition in a comprehension if you find it more readable:
def add_index(nums): return [add+num for add,num in enumerate(nums,1)]
For a list of lists ['"fo"', '"ba"', '1','2','ect.','"fo"', '"ba"','ect.','57','"trip"'] , what's the cleanest way to get all the indices for '"fo"' when '"fo"','"ba"' appear together in the list. in Python?
Similar to one edited for 1 item answered Dec 30'14 at 21:03 and Edited Jul 28 at 21:30 by MrWonderful
For a list ["foo", "bar", "baz"] and an item in the list "bar", what's the cleanest way to get its index (1) in Python?
If you're looking for '"fo"' immediately followed by '"ba"', something like
import itertools
l = ['"fo"', '"ba"', '1','2','ect.','"fo"', '"ba"','ect.','57','"trip"']
print([i for i, x in enumerate(zip(l, itertools.islice(l, 1, None))) if x == ('"fo"', '"ba"')])
This should do it:
for one_list in list_of_lists:
if ("fo" in one_list ) and ("ba" in one_list):
return indices = [i for i, x in enumerate(one_list) if x == "fo"]
You could try this! We iterate through the list once, checking if the index we are on and the next thing down match what you want. If it does, we add it to a list. We also check that we are not on the last index of the list to avoid indexOutOfBounds exceptions.
results = []
for i in range(0, len(lst)):
if i < len(lst)-1 and lst[i] == '"fo"' and lst[i+1] == '"ba"':
results.append(i)
return results
Note that this works for your example, which looks to be a single list rather than a list of lists. To apply to lists of lists, you could add an extra for loop iteration through each sublist.
This is what I ended up with. I adapted Patrick Haugh's answer.
import itertools # C-D create list of indices
r_va=('"EMD"', '"20170820"')
L = ([i for i, x in enumerate(zip(l, itertools.islice(l, 1, None))) if \
x == (r_va)])
e =(len(l))
L.append(e) # adds end length of no_spaces L is list of indexes of l
i have this
lst = [['100','LA'],['101','NY'],['100','NC']]
lst2 = []
i need to check if there's any 100,101,etc repeated and remove the repeated numbers. So the second list would look like this
lst2=[['100','LA'],['101','NY']]
because the 100 was already added once in that second list
A quick and dirty way to do this is using a generic uniqueness filter:
def uniqueness(iterable,key=lambda x:x):
seen = set()
for item in iterable:
fitem = key(item)
if fitem not in seen:
yield item
seen.add(fitem)
You can then use it like:
list2 = list(uniqueness(lst,key=lambda x:x[0]))
If you do not specify, the filter will assume the entire element (but this will fail here, because list is not hashable).
An answer without lambda's.
nmbrs = [n for n, city in lst]
lst2 = [x for i, x in enumerate(lst) if x[0] not in nmbrs[:i]]
I have a list of lists of tuples of integers.
ls = [[(a_1, a_2), (b_1, b_2)], [(c_1, c_2), (d_1, d_2), (e_1, e_2)], ...]
And I need to delete every item of ls that contains a tuple whose second entry is equal to a predetermined integer.
I tried this:
for item in ls:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
But for some reason, this only removes a few of the list items but not all containing a tuple with second entry = m.
Use a list comprehension:
ls = [item for item in ls if all(tuple[1] != m for tuple in item)]
Or use a filter:
ls = filter(lambda item: all(tuple[1] != m for tuple in item),ls)
Code sucks and we need less of it - here's as sparse as it gets.
[l for l in ls if m not in [i[1] for i in l]]
The best way to filter a list in python is to use a list comprehension:
filtered = [item for item in ls if not(contains_m(item))]
And then all you need is a function that can tell if an item contains m, for example:
def contains_m(item):
return any([tpl[1] == m for tpl in item])
Removing an itme from list is not a good idea while iterating though it.
Try that (if where are talking Python here)
ls = [[('a_1', 'a_2'), ('b_1', 'b_2')], [('c_1', 'c_2'), ('d_1', 'd_2'), ('e_1', 'e_2')]]
m='c_2'
print [ x for x in ls if not [ y for y in x if y[1]==m ]]
Python's list iterator is lazy. This means that when you remove an item from the list, it will skip the next item. For example, say you want to remove all ones from the following list:
[1, 1, 2]
Your for loop starts at index 0:
[1, 1, 2]
^
It removes the element and moves on:
[1, 2]
^
This example is just to help illustrate the issue. One simple workaround is to loop backwards using the index:
for ind in range(len(ls)-1, -1, -1):
item = ls[ind]
for tpl in item:
if tpl[1] == m:
del ls[ind]
break # You can end the inner loop immediately in this case
Another way is to make a copy of the list to iterate over, but remove from the original:
for item in ls[:]:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
break
The last approach can be simplified into creating an output list that contains only the elements that you want. This is easiest to do with a list comprehension. See #AlexeySmirnov 's answer for the best way to do that.
I have a list which comes from a text file that I have parsed using very primitive regular expressions. I would like to reorganize a more spartan list that contains only files with a date immediately following. I've tried looping through the list using len() but that will only extract the files and not the next entry. Many thanks in advance.
This:
2014-01-28
part002.csv.gz
2014-01-28
part001.csv.gz
2014-01-28
2014-01-28
2014-01-27
2014-01-27
2014-01-26
2014-01-26
2014-01-25
part002.csv.gz
2014-01-25
Becomes this:
part002.csv.gz
2014-01-28
part001.csv.gz
2014-01-28
part002.csv.gz
2014-01-25
You can use a list comprehension:
filtered = [e for i, e in enumerate(l) if not isDate(e) or (i > 0 and not isDate(l[i-1]))]
Complete example:
l = ['2014-01-28', 'part002.csv.gz', '2014-01-28', 'part001.csv.gz', '2014-01-28', '2014-01-28', '2014-01-27', 'part002.csv.gz', '2014-01-25']
def isDate (s):
return '.' not in s
filtered = [e for i, e in enumerate(l) if not isDate(e) or (i > 0 and not isDate(l[i-1]))]
print (filtered)
Explained:
l is our original list.
isDate takes a string and tests whether it is a date (in my simple example it just checks that it doesn't contain a period, for better results use regex or strptime).
enumerate enumerates a list (or anything iterable, I will now stick to the word list, just in order not to get too technical). It returns a list of tuples; each tuple containing the index and the element of the list passed to enumerate. For instance enumerate (['a', None, 3]) makes [(0,'a'),(1,None),(2,3)]
i, e = unpacks the tuple, assigning the index to i and the element to e.
A list comprehension works like this (simplyfied): [x for x in somewhere if cond(x)] returns a list of all elements of somewhere which comply with the condition cond(x).
In our case we only add elements to our filtered list, if they are no dates (not the fruit) not isDate(e) or if they are not at the beginning i > 0 and at the same time their predecessor is not a date not isDate(l[i-1]) (that is, a file).
In pseudocode:
Take list `l`
Let our filtered list be an empty list
For each item in `l` do
let `i` be the index of the item
let `e` be the item itself
if `e` is not a Date
or if `i` > 0 (i.e. it is not the first item)
and at the sametime the preceding item is a File
then and only then add `e` to our filtered list.
Store the previous line at each line, then you always have have it when you need it
previous_line = None
newlist = []
for line in lines:
if isdate(line):
newlist.append(previous_line)
previous_line = line
Defining isdate:
import datetime
def isdate(s):
try:
datetime.datetime.strptime(s, '%Y-%m-%d')
except:
return False
else:
return True
Working through it:
s = """
#that long string, snipped
"""
li = [x for x in s.splitlines() if x]
li
Out[3]:
['2014-01-28',
'part002.csv.gz',
'2014-01-28',
'part001.csv.gz',
'2014-01-28',
'2014-01-28',
'2014-01-27',
'2014-01-27',
'2014-01-26',
'2014-01-26',
'2014-01-25',
'part002.csv.gz',
'2014-01-25']
[tup for tup in zip(li,li[1:]) if 'csv' in tup[0]] #shown for dicactic purposes, gen expression used below
Out[7]:
[('part002.csv.gz', '2014-01-28'),
('part001.csv.gz', '2014-01-28'),
('part002.csv.gz', '2014-01-25')]
The actual answer:
from itertools import chain
list(chain.from_iterable(tup for tup in zip(li,li[1:]) if 'csv' in tup[0]))
Out[9]:
['part002.csv.gz',
'2014-01-28',
'part001.csv.gz',
'2014-01-28',
'part002.csv.gz',
'2014-01-25']
Essentially: zip (in python 2, use izip) the list together with itself, one index advanced. Iterate over the pairwise tuples, filtering out those that don't have a file-like string for their first element. Lastly, flatten the tuples into a list using itertools.chain to achieve your desired output.