Function to determine if adjacent elements are alike - python

I've been stuck on this for a while and I keep running into problems, I'm trying to create a function that returns true if at least one pair of adjacent elements in a list are equal.
Test cases:
[1, 2, 3] -> False
[1, 2, 2, 3] -> True
[2, 6, 3, 6] -> False
['a', 'b', 'c', 'd', 'd'] -> True
def equal_adjacent_elements(l):
for x in range(len(l)):
if l[x] == l[x+1] or l[x] == l[x-1]:
return True
else:
return False
The problems I run into are assertion errors and I believe it's because of my loop. Once I find a pair that is equal the returned value won't stay the same because my loops will evaluate the next values in the list. So I just need to find at least one pair, I don't know how I would do that though.

You can zip the list with itself offest by 1 and use any to short-cut the find-one pattern:
def equal_adjacent_elements(l):
return any(x == y for x, y in zip(l, l[1:]))

I made few changes. It should work now.
def equal_adjacent_elements(l):
for x in range(len(l)-1):
if l[x] == l[x+1]:
return True
return False
or, shorter one using any,
def equal_adjacent_elements(l)
return any( l[x] == l[x+1] for x in range(len(l)-1) )

There are two problems here:
the indices can run into overflow here;
you immediately return False from the moment there are two consecutive elements that are not equal, you should return False after the for loop.
The index problem here is that x ranges from 0 to (excluding) len(l). So that means x-1 ranges from -1 (which is the last element of the list) to len(l)-1 and x+1 from 1 to len(l) (including). But the list is not that long, so you get an index out of the list bounds, which is an error.
A more Pythonic approach however is to use a zip(..) over the list l, and the "tail" of the list (the list omitting the first element). So zip(l, l[1:]).
We can iterate over every pair x,y of l and l[1:]. In case x == y, then we have such element and return True.
In case we fail to find such pair, we eventually return `False.
So a correct implementation is:
def equal_adjacent_elements(l):
for x,y in zip(l, l[1:]):
if x == y:
return True
return False
Python however has a builtin any, that will return True from the moment the iterable we give it contains at least one True; and False if no element has truthiness True.
So we can convert the above code to something using the any builtin:
def equal_adjacent_elements(l):
return any(x == y for x,y in zip(l, l[1:]))

I'm kinda new to python but anyways hoped this is easy enough
def equal_adjacent_elements(l):
try:
for i in range(0, len(l)):
if l[i] == l[i+1]:
return True
except IndexError:
return False

Related

writing a function that checks if tuples, lists and strings are sorted

I'm trying to build a function that prints true if the tuples, lists and strings inputted are sorted, and False if not. I've tried two different methods but neither worked.. Could anyone tell me what part is wrong? Thank you !!!
def is_ordered (*args):
for i in range(1,len(args)):
if args[i - 1] > args[i]:
return True
else:
return False
def is_ordered (*args):
if args == args.sorted()
return True
else:
return False
Here are the lists and tuples I created.
sorted_list = [1,2,3,4,5,6,7]
is_ordered(sorted_list)
unsorted_list = [41,3,35,4,45,6,7]
is_ordered(unsorted_list)
sorted_tuple = (1,2,3,4,5,6,7)
is_ordered(sorted_tuple)
unsorted_tuple = (41,3,35,4,45,6,7)
is_ordered(unsorted_tuple)
stri = "datascience"
is_ordered(stri)
You don't actually need to sort the input to tell if it's sorted. You just need to see if each item is less than or equal to the item before it and return False if that's ever not the case. This will be more efficient than sorting, then checking.
You can compare items with the neighbor by zipping the list with itself at an offset like zip(seq, seq[1:].
def is_ordered (seq):
'''Return true if every item is less than or equal the item after it'''
return all(a <= b for a, b in zip(seq, seq[1:]))
is_ordered('abcd')
#True
is_ordered('abdag')
#False
is_ordered([1, 2, 3, 4])
#True
If you want to use sorted(), don't use *args just accept a sequence as an argument and understand that sorted(someString) will not equal a string because it makes a list. So you need to compare like things:
def is_ordered (seq):
return list(seq) == sorted(seq)
is_ordered((1, 2, 3))
#True
is_ordered((1, 2, 3, 0))
#False
is_ordered("abcd")
# True
is_ordered("abcda")
# False

Function Definition: Printing a list of even integers

I'm trying to define a function that returns a list of even integers from a list of overall integers
def print_even_numbers(n: list):
'''Return a list of even numbers given a list of integers'''
for x in list:
if x % 2 == 0:
return(x)
When I tried the code above, the error says that the type isn't iterable
list is the name of the list type. So you cannot iterate over a type. you should use n. Second, your return is indented wrong. It should be on the top function level, because return exits the function. Then you need to collect the result somewhere.
def print_even_numbers(n):
'''Return a list of even numbers given a list of integers'''
result = []
for x in n:
if x % 2 == 0:
result.append(x)
return result
This can be written in short by a list comprehension:
def print_even_numbers(n):
'''Return a list of even numbers given a list of integers'''
return [x for x in n if x % 2 == 0]
Wrong python syntax:
def print_even_numbers(n: list):
You don't need brackets:
return(x)
Wrong indentation. And wrong condition. (And don't use reserved python words such a list for your own variables.
for x in list:
Summarize:
def print_even_numbers(n):
'''Return a list of even numbers given a list of integers'''
result = []
for x in n:
if x % 2 == 0:
result.append(x)
return result
print print_even_numbers(range(10))
>>> [0, 2, 4, 6, 8]
And finally more pythonic way is to use yield to implement desired behaviour:
def gen_even_numbers(n):
for x in n:
if x % 2 == 0:
yield x
print list(gen_even_numbers(range(10)))
>>> [0, 2, 4, 6, 8]
you can use the filter built-in
def print_even_numbers(lst):
return list(filter(lambda x: not x%2, lst))
Note: on python 2 filter returns a list already so there is no need to convert it
def print_even_numbers(lst):
return filter(lambda x: not x%2, lst)
By the way, the function is named print_even_numbers but it does not print anything ;)

Python - check if a letter is in a list

If a letter (string) is in a list,
find_letter(['o', ['hello', 'c', 'bye']),
return True, if not return False.
def find_letter(lst):
lst=['o','hello', 1]
n='o'
if not lst:
return 0
elif lst[0] == n:
return True
elif find_letter(lst[0:]):
return True
else:
return False
print(find_letter(lst))
It does return 'True', but I am not sure if this is the right way to do this. Maybe there's a better way? In the second elif-statement, is python going through all the elements in the list if the first one doesn't contain the letter? The function must be recursive.
I think the most pythonic approach would be to use
def find_letter(letter, lst):
return any(letter in word for word in lst)
The beauty of this is that it iterates over lst and returns as soon as one of the words in that list contains letter. Also, it doesn't need to recurse.
This returns False instead of 0 if lst is empty, though (unlike your program) but since False evaluates to 0 anyway (and vice versa), that's not really an issue.
Since you need a recursive version:
Short version
def find_letter(let, lst):
return (lst or False) and \
((isinstance(lst[0], str) and let in lst[0]) or find_letter(let, lst[1:]))
More explicit version
def find_letter(let, lst):
if lst:
e = lst[0]
return (isinstance(e, str) and let in e) or find_letter(let, lst[1:])
return False
Even more explicit version
def find_letter(let, lst):
if lst:
e = lst[0]
if isinstance(e, str) and let in e:
return True
return find_letter(let, lst[1:])
return False
Note that I leave out a couple of else: because they are not necessary after a return statement. If you don't want to test for a letter in a string, but just for equality, replace let in ... by let == ....
Here is your error
def find_letter(lst): # You receive your list as lst
lst=['o','hello', 1] # Opppsss! You override it. It does not matter what you receive with lst above, now its value is ['o','hello', 1]
n='o'
So in find_letter(lst[0:]), you use list slicing, but on lst=['o','hello', 1] line, you override it again and you always execute your search on the first element of the list.
n = "o" # you can set this too, but this is optional
def find_letter(lst):
# do not set a value to lst in here
if not lst:
return 0
elif lst[0] == n: # You checked first element in here
return True
elif find_letter(lst[1:]): # since you checked the first element, skip it and return the orher elements of the list
return True
else:
return False
lst = ['o','hello', 1]
print find_letter(lst)
You want to find the Membership
Please refer this code to resolve your problem.
Suppose
list1 = ['physics', 'chemistry', 1997, 2000];
list2 = [1, 2, 3, 4, 5, 6, 7 ];
print "list1[0]: ", list1[0]
print "list2[1:5]: ", list2[1:5]
print 3 in list2
Output:
list1[0]: physics
list2[1:5]: [2, 3, 4, 5]
True
Just realized OP wants to check A string only
You can define a function and match the string in a list recursively like this:
def plist(lst, n):
# loop inside the list
for each in lst:
# if "each" is also a list (nested), check inside that list, too
if isinstance(each, list):
# this will reuse your "plist" and loop over any nested list again
plist(each, n)
# if n matches any element in the list, return True
if any(n in each_letter for each_letter in each):
return True
# if after looping over your list + nested list, return False if no match is find
else:
return False
>> lst = ['o', ['hello', 'c', 'bye']]
>> plist(lst, 'o')
>> True
>> plist(lst, 'h')
>> True
>> plist(lst, 'z')
>> False
Hope this solves your problem.
Here is a one line lambda:
any(list(map(lambda x: True if n in str(x) else False,lst )))
data:
lst=['o','hello', 1]
n='o'
output 1:
True
note:
any() checks if any True, then True - otherwise False - so without the any() we get:
list(map(lambda x: True if n in str(x) else False,lst ))
output 2:
[True, True, False]

Algorithm similar to 'Fizzbuzz'

I have a function
def process_list(mylist):
return [x for x in mylist if isinstance(x, int)];
I need to modify this function so that in the new list that is returned, every integer divisible by 3 is replaced by -1, every integer divisible by 5 is replaced by -2, and every integer divisible by both is replaced by -3. Other integers are left unchanged. As before non-integers should be dropped.
Thus, process_list([1, 3, 5, 15, 22, 'b']) should return [1, -1, -2, -3, 22].
I can do this by using if-else. But I want to know the pythonic way of doing it.
Well, pythonic for me is not a synonym for one-liner.
See this.
Because flat is better than nested and sparse is better than dense
def process_list(mylist):
# filter, prefer generator expression
tmp = (x for x in mylist if isinstance(x, int))
# mapping logic
mappings = ((15, -3), (5, -2), (3, -1))
def fizzbuzz(num):
try:
return next(v for k, v in mappings if num%k == 0)
except StopIteration:
return num
# return a mapped list
return map(fizzbuzz, tmp)
You can change the function like this.
def process_list(mylist):
return [(-3 if x % 15 == 0 else (-2 if x % 5 == 0 else ( -1 if x % 3 == 0 else x))) for x in mylist if isinstance(x, int)]
I cannot say that this is the best way, but as someone that is not fond of long if .. else chains, I would rewrite Hannes Ovrén's filter as
def convert_ints(x, dividers=(15, 5 ,3)):
for val, div in enumerate(dividers):
if (x%div)==0:
return -len(dividers)+val
return x
This is scalbale solution, that may be easily expanded
EDIT:
for more complicated cases, a tuple of lamdba-s may be used:
conditions=(lambda x:x%15==0, lambda x:x%5==0, lambda x:x%3==0)
I think the pythonic way is to use if-else in this case.
For example
def process_list(mylist):
return list_filter(x) for x in mylist if isinstance(x, int)]
def list_filter(x):
if x % 3 == 0:
return -1
elif ... # <snip>
(even though I'd probably rewrite the process_list function as a for loop that builds a new list)
Using list comprehension will most likely just be a lot harder to read, and/or require multiple passes.

Python Lists: How can I search for another element or duplicate item in a list

I have a list say p = [1,2,3,4,2]
Is there any way of returning bool value True if it contains a duplicate using only find, indexing, slicing, len() etc methods and not dict, tuple etc.
I used this code:
for e in p:
duplicate = p.find(e, e+1)
if duplicate in p:
return True
Here is the easy way:
return len(p) != len(set(p))
A less efficient way that doesn't use set:
for i in range(len(p)):
if p[i] in p[i+1:]:
return True
return False
This second approach is not very idiomatic, but avoids all but the most basic features of the language (including tuples).
Here is one more way:
while p:
e = p.pop()
if e in p:
return True
return False
This is simple, but does modify the list.
One final way I am going to demonstrate is:
s = sorted(p)
for i in range(1, len(s)):
if s[i] == s[i - 1]:
return True
return False
This works by sorting p and then comparing every pair of consecutive elements.
You could also use list.count:
def has_duplicates(p):
for e in p:
if p.count(e) > 1:
return True
return False
>>> p = [1, 2, 3, 4, 2]
>>> len(set(p)) == len(p)
False
You can find more information about sets in the Python Documentation.
If you have to do it this way, you could do:
def has_duplicates(lst):
for i, e in enumerate(lst[::-1]):
if lst.index(e) != len(lst) - i - 1:
return True
return False
This iterates through the list in reverse order (since index searches from the start of the list). But it's better simply to do:
def has_duplicates(lst):
return len(set(lst)) != len(lst)
Using collections.Counter
>>> import collections
>>> p
[1, 2, 3, 4, 2]
>>> if collections.Counter(p).most_common()[0][1] > 1:
... print('duplicate found')
...
duplicate found
>>> if collections.Counter(set(p)).most_common()[0][1] > 1:
... print('duplicate found')
...
>>>
Here's a very simple way to do it. It may be slow for very large lists.
def has_duplicates(lst):
for e in lst:
lst = lst[1:]
if e in lst: return True
return False

Categories

Resources