I have lists that are empty and filled in the data. I am trying to the store last element of the list into a variable. If there are elements in the list, it is working fine. However, when I pass in a empty [] list, I get error like: IndexError: list index out of range. Which syntax I should be using for []?
ids = [
'abc123',
'ab233',
'23231ad',
'a23r2d23'
]
ids = []
# I tried these for empty
final = [ids if [] else ids[-1]] #error
# final = [ids if ids == None else ids == ids[-1]] # error
# final = [ids if ids == [] else ids == ids[-1]] # gives [[]] instead of []
print(final)
Basically, if an empty list is in ids, I need it to give []. If there are elements, then give the last element, which is working.
Here is one way to do this:
final = ids[-1] if ids else None
(Replace None with the value you'd like final to take when the list is empty.)
you can check for a empty list by below expression.
data = []
if data: #this returns False for empty list
print("list is empty")
else:
print("list has elements")
so what you can do is.
final = data[-1] if data else []
print(final)
final = ids[-1] if len(ids) > 0 else []
This will handle the immediate problem. Please work through class materials or tutorials a little more for individual techniques. For instance, your phrase ids if [] doesnt' do what you (currently) seem to think: it does not check ids against the empty list -- all it does is to see whether that empty list is "truthy", and an empty list evaluates to False.
You are getting the error because you wont be able to select the last item if the list is empty and it will rightfully throw an IndexError.
Try this example
ids = [[i for i in range(10)] for x in range(3)]
ids.append([])
last_if_not_empty = [i[-1] for i in ids if i]
Here you filter out the non-empty list by if i which is the condition to select not empty lists. From there you can pick out the last elements of the lists.
a = list[-1] if not len(list)==0 else 0
Related
I am making a console game using python and I am checking if an item is in a list using:
if variable in list:
I want to check which variable in that list it was like list[0] for example. Any help would be appreciated :)
You can do it using the list class attribute index as following:
list.index(variable)
Index gives you an integer that matches the location of the first appearance of the value you are looking for, and it will throw an error if the value is not found.
If you are already checking if the value is in the list, then within the if statement you can get the index by:
if variable in list:
variable_at = list.index(variable)
Example:
foo = ['this','is','not','This','it','is','that','This']
if 'This' in foo:
print(foo.index('This'))
Outputs:
3
Take a look at the answer below, which has more complete information.
Finding the index of an item in a list
We may be inspired from other languages such as Javascript and create a function which returns index if item exists or -1 otherwise.
list_ = [5, 6, 7, 8]
def check_element(alist: list, item: any):
if item in alist:
return alist.index(item)
else:
return -1
and the usage is
check1 = check_element(list_, 5)
check2 = check_element(list_, 9)
and this one is for one line lovers
check_element_one_liner = lambda alist, item: alist.index(item) if item in alist else -1
alternative_check1 = check_element_one_liner(list_, 5)
alternative_check2 = check_element_one_liner(list_, 9)
and a bit shorter version :)
check_shorter = lambda a, i: a.index(i) if i in a else -1
Using a librairy you could use numpy's np.where(list == variable).
In vanilla Python, I can think of something like:
idx = [idx for idx, item in enumerate(list) if item == variable][0]
But this solution is not fool proof, for instance, if theres no matching results, it will crash. You could complete this using an if right before:
if variable in list:
idx = [idx for idx, item in enumerate(list) if item == variable][0]
else:
idx = None
I understand that you want to get a sublist containing only the elements of the original list that match a certain condition (in your example case, you want to extract all the elements that are equal to the first element of the list).
You can do that by using the built-in filter function which allows you to produce a new list containing only the elements that match a specific condition.
Here's an example:
a = [1,1,1,3,4]
variable = a[0]
b = list(filter(lambda x : x == variable, a)) # [1,1,1]
This answer assumes that you only search for one (the first) matching element in the list.
Using the index method of a list should be the way to go. You just have to wrap it in a try-except statement. Here is an alternative version using next.
def get_index(data, search):
return next((index for index, value in enumerate(data) if value == search), None)
my_list = list('ABCDEFGH')
print(get_index(my_list, 'C'))
print(get_index(my_list, 'X'))
The output is
2
None
assuming that you want to check that it exists and get its index, the most efficient way is to use list.index , it returns the first item index found, otherwise it raises an error so it can be used as follows:
items = [1,2,3,4,5]
item_index = None
try:
item_index = items.index(3) # look for 3 in the list
except ValueError:
# do item not found logic
print("item not found") # example
else:
# do item found logic knowing item_index
print(items[item_index]) # example, prints 3
also please avoid naming variables list as it overrides the built-in function list.
If you simply want to check if the number is in the list and print it or print it's index, you could simply try this:
ls = [1,2,3]
num = 2
if num in ls:
# to print the num
print(num)
# to print the index of num
print(ls.index(num))
else:
print('Number not in the list')
animals = ['cat', 'dog', 'rabbit', 'horse']
index = animals.index('dog')
print(index)
I'm trying to create the following datastructure (list containing several lists) within a shared dict:
{'my123': [['TEST'],['BLA']]}
code:
records = manager.dict({})
<within some loop>
dictkey = "my123"
tempval = "TEST" # as an example, gets new values with every loop
list = []
list.append(tempval)
if dictkey not in records.keys():
records[dictkey] = [list]
else:
records[dictkey][0].append([tempval])
The first list within the dict element 'my123' gets populated with "TEST", but when I loop a second time (where tempval is "BLA"), the list doesn't get nested.
Instead I'm getting:
{'my123': [['TEST']]}
What am I doing wrong in the else statement?
Edit:
Have modified the code, but still doesn't get added:
records = manager.dict({})
<within some loop>
dictkey = "my123"
tempval = "TEST" # as an example, gets new values with every loop
list = []
list.append(tempval)
if dictkey == "my123":
print tempval # prints new values with every loop to make sure
if dictkey not in records.keys():
records[dictkey] = [list]
else:
records[dictkey].append([list])
Remove the [0] part from the last line. The value in the dictionary is already a list. It is that list you wish to append the second list (['BLA']) to.
You're almost there. You will want to append the list like so:
records = manager.dict({})
# within some loop
dictkey = "my123"
tempval = "TEST" # as an example, gets new values with every loop
temp_list = [tempval] # holds a list of value
if dictkey not in records:
records[dictkey] = [temp_list]
else:
records[dictkey].append(temp_list) # append list of value
I've found the solution. Looks like the append in the else statement doesn't work for class multiprocessing.managers.DictProxy.
I've modified the else statement and now it's working.
records = manager.dict({})
< within some loop >
dictkey = "my123"
tempval = "TEST" # as an example, gets new values with every loop
temp_list = [tempval] # holds a list of value
if dictkey not in records:
records[dictkey] = [temp_list]
else:
records[dictkey] = records.get(dictkey, []) + [temp_list]
Thanks everyone for your help!
I'm looking for a string function that removes one duplicate pair from multiple duplicates.
What i'd like the function to do:
input = ['a','a','a','b','b','c','d','d','d','d']
output = ['a','c']
heres what I have so far:
def double(lijst):
"""
returns all duplicates in the list as a set
"""
res = set()
zien = set()
for x in lijst:
if x in zien or zien.add(x):
res.add(x)
return(res)
def main():
list_1 = ['a','a','a','b','b','c']
list_2 = set(list_1)
print(list_2 - double(list_1))
main()
The problem being that it removes all duplicates, and doesn't leave the 'a'. Any ideas how to approach this problem?
For those interested why I need this; I want to track when a levehnstein function is processing vowel steps, if a vowel is being inserted or deleted I want to assign a different value to 'that step' (first I need to tract if a vowel has passed on either side of the matrix before the current step though) hence I need to remove duplicate pairs from a vowel list (as explained in the input output example).
These solves your problem. Take a look.
lsit = ['a','a','a','b','b','c']
for i in lsit:
temp = lsit.count(i)
if temp%2==0:
for x in range(temp):
lsit.remove(i)
else:
for x in range(temp-1):
lsit.remove(i)
print lsit
Output:
['a','c']
Just iterate through the list. If an element does not exist in the result, add it to the set. Or if there does already have one in the set, cancel out those two element.
The code is simple:
def double(l):
"""
returns all duplicates in the list as a set
"""
res = set()
for x in l:
if x in res:
res.remove(x)
else:
res.add(x)
return res
input = ['a','a','a','b','b','c','d','d','d','d']
print double(input)
I looked up and found a close example, but the answer found in this link: Remove adjacent duplicate elements from a list won't run the test cases for this problem. So this is all I have so far:
def remove_dups(thelist):
"""Returns: a COPY of thelist with adjacent duplicates removed.
Example: for thelist = [1,2,2,3,3,3,4,5,1,1,1],
the answer is [1,2,3,4,5,1]
Precondition: thelist is a list of ints"""
i = 1
if len(thelist) == 0:
return []
elif len(thelist) == 1:
return thelist
elif thelist[i] == thelist[i-1]:
del thelist[i]
return remove_dups(thelist[i:])
def test_remove_dups():
assert_equals([], remove_dups([]))
assert_equals([3], remove_dups([3,3]))
assert_equals([4], remove_dups([4]))
assert_equals([5], remove_dups([5, 5]))
assert_equals([1,2,3,4,5,1], remove_dups([1,2,2,3,3,3,4,5,1,1,1]))
# test for whether the code is really returning a copy of the original list
mylist = [3]
assert_equals(False, mylist is remove_dups(mylist))
EDIT while I do understand that the accepted answer linked above using itertools.groupby would work, I think it wouldn't teach me what's wrong with my code & and would defeat the purpose of the exercise if I imported grouby from itertools.
from itertools import groupby
def remove_dups(lst):
return [k for k,items in groupby(lst)]
If you really want a recursive solution, I would suggest something like
def remove_dups(lst):
if lst:
firstval = lst[0]
# find lowest index of val != firstval
for index, value in enumerate(lst):
if value != firstval:
return [firstval] + remove_dups(lst[index:])
# no such value found
return [firstval]
else:
# empty list
return []
Your assertion fails, because in
return thelist
you are returning the same list, and not a copy as specified in the comments.
Try:
return thelist[:]
When using recursion with list it is most of the time a problem of returning a sub-list or part of that list. Which makes the termination case testing for an empty list. And then you have the two cases:
The current value is different from the last one we saw so we want to keep it
The current value is the same as the last one we saw so we discard it and keep iterating on the "rest" of the values.
Which translate in this code:
l = [1,2,2,3,3,3,4,5,1,1,1]
def dedup(values, uniq):
# The list of values is empty our work here is done
if not values:
return uniq
# We add a value in 'uniq' for two reasons:
# 1/ it is empty and we need to start somewhere
# 2/ it is different from the last value that was added
if not uniq or values[0] != uniq[-1]:
uniq.append(values.pop(0))
return dedup(values, uniq)
# We just added the exact same value so we remove it from 'values' and
# move to the next iteration
return dedup(values[1:], uniq)
print dedup(l, []) # output: [1, 2, 3, 4, 5, 1]
problem is with your return statement,
you are returning
return remove_dups(thelist[i:])
output will be always last n single element of list
like for above soon,
print remove_dups([1,2,2,3,3,3,4,5,1,1,1])
>>> [1] #as your desired is [1,2,3,4,5,1]
which returns finally a list of single element as it don't consider Oth element.
here is recursive solution.
def remove_dups(lst):
if len(lst)>1:
if lst[0] != lst[1]:
return [lst[0]] + remove_dups(lst[1:])
del lst[1]
return remove_dups(lst)
else:
return lst
I am trying to remove duplicates from the list of unicode string without changing the order(So, I don't want to use set) of elements appeared in it.
Program:
result = [u'http://google.com', u'http://www.catb.org/esr/faqs/hacker-howto.html', u'http://www.catb.org/~esr/faqs/hacker-howto.html',u'http://amazon.com', u'http://www.catb.org/esr/faqs/hacker-howto.html', u'http://yahoo.com']
result.reverse()
for e in result:
count_e = result.count(e)
if count_e > 1:
for i in range(0, count_e - 1):
result.remove(e)
result.reverse()
print result
Output:
[u'http://google.com', u'http://www.catb.org/esr/faqs/hacker-howto.html', u'http://www.catb.org/~esr/faqs/hacker-howto.html', u'http://amazon.com', u'http://yahoo.com']
Expected Output:
[u'http://google.com', u'http://catb.org/~esr/faqs/hacker-howto.html', u'http://amazon.com', u'http://yahoo.com']
So, Is there any way of doing it simple as possible.
You actually don't have duplicates in your list. One time you have http://catb.org while another time you have http://www.catb.org.
You'll have to figure a way to determine whether the URL has www. in front or not.
You can create a new list and add items to it if they're not already in it.
result = [ /some list items/]
uniq = []
for item in result:
if item not in uniq:
uniq.append(item)
You could use a set and then sort it by the original index:
sorted(set(result), key=result.index)
This works because index returns the first occurrence (so it keeps them in order according to first appearance in the original list)
I also notice that one of the strings in your original isn't a unicode string. So you might want to do something like:
u = [unicode(s) for s in result]
return sorted(set(u), key=u.index)
EDIT: 'http://google.com' and 'http://www.google.com' are not string duplicates. If you want to treat them as such, you could do something like:
def remove_www(s):
s = unicode(s)
prefix = u'http://'
suffix = s[11:] if s.startswith(u'http://www') else s[7:]
return prefix+suffix
And then replace the earlier code with
u = [remove_www(s) for s in result]
return sorted(set(u), key=u.index)
Here is a method that modifies result in place:
result = [u'http://google.com', u'http://catb.org/~esr/faqs/hacker-howto.html', u'http://www.catb.org/~esr/faqs/hacker-howto.html',u'http://amazon.com', 'http://www.catb.org/esr/faqs/hacker-howto.html', u'http://yahoo.com']
seen = set()
i = 0
while i < len(result):
if result[i] not in seen:
seen.add(result[i])
i += 1
else:
del result[i]