Find a unique elements as a list on list - python

I have a Python Task for online course on Udacity although I put the right code for the task it still gives me that is wrong answer. Can any one tell me why??
You are required to complete the function unique_list(l). where "l" is a list of numbers. the function is expected to return the unique numbers in that list.
Example:
input : [1,1,1,2,2,3,3,3,3,4,5,5,6]
output: [1,2,3,4,5,6]
no_list=[22,22,2,1,11,11,3,3,3,4,5,5,5,55,55,66]
def unique_list(l):
l = list(set(no_list))
l.sort()
return l
print(unique_list(no_list))
l = list(set(no_list))
l.sort()
return l
this part is my answer the other is from udacity site

Your function should make use of the argument l instead of using the global variable no_list:
def unique_list(l):
l = list(set(l))
l.sort()
return l

First, as #blhsing had already noted, you're manipulating the global variable, not the one passed to the function. Still, I think that your code may be suffering from another problem, which is your assumption that all lists that are being passed to your function are sorted, some of them may not be sorted, but when you sort them, you're losing the original order, and I'm guessing that one of the problem requirements is maintaining the order of the elements in the original list, and to do that in Python, you could sort using the index as a key:
def unique_list(l):
return sorted(set(l), key = l.index)

If you are allowed to use package, you can use numpy which can come handy.
Using numpy it can be done as :
import numpy as np
def unique_list(l):
return np.unique(np.array(l))
If you want to return list, you can simply:
import numpy as np
def unique_list(l):
return list(np.unique(np.array(l)))

Use this code, They want a certain order
no_list = [22,22,2,1,11,11,2,2,3,3,3,4,5,5,5,55,55,66]
def unique_list(l):
x = []
for a in l:
if a not in x:
x.append(a)
return x
print(unique_list(no_list))

Related

Check if an item is always followed by another in a list - Python

I would like to check if one item is always followed with another within a list. I have come up with this really trite example... Let's say I would like to check if "a" is always followed by "b" in the following list:
list = ['x','y','z','a','b','2','3','5','2','1','5','fds','f','s','a','b']
Then, ideally, the function would return TRUE if every time we see an "a", it is directly followed by a "b". Can anyone help me with this? Maybe I am missing something really simple here.
all(a != 'a' or b == 'b' for a, b in zip(list[:-1], list[1:]))
You can use all with zip for an O(n) solution.
itertools.islice is used to avoid the expensive of making a new list. You can also wrap in a function as below.
from itertools import islice
def fun(lst, val1, val2):
return all(j==val2 for i, j in zip(lst, islice(lst, 1, None)) if i==val1)
lst = ['x','y','z','a','b','2','3','5','2','1','5','fds','f','s','a','b']
res = fun(lst, 'a', 'b')
print(res) # True

modifying argument value within function

I am trying to figure out a way to modify the order of a list of tuples within a function without returning the list.
For example:
L = [(2,4),(8,5),(1,3),(9,4)]
def sort_ratios(L):
L = sorted(L, key=lambda x: float(x[0])/float(x[1]))
return L
Thus, calling sort_ratios() outputs:
>>>sort_ratios(L)
[(1,3),(2,4),(8,5),(9,4)]
But L would still be [(2,4),(8,5),(1,3),(9,4)]
Instead, I would like to simply modify the value of L without returning anything so that sort_ratios() operates as follows:
>>>sort_ratios(L)
>>>L
[(1,3),(2,4),(8,5),(9,4)]
It seems trivial, but I just can't seem to get the function to operate this way.
Try L.sort(key=lambda x: float(x[0])/float(x[1])) for an in-place sort.

Accessing elements of multi-dimensional list, given a list of indexes

I have a multidimensional list F, holding elements of some type. So, if for example the rank is 4, then the elements of F can be accessed by something like F[a][b][c][d].
Given a list L=[a,b,c,d], I would like to access F[a][b][c][d]. My problem is that my rank is going to be changing, so I cannot just have F[L[0]][L[1]][L[2]][L[3]].
Ideally, I would like to be able to do F[L] and get the element F[a][b][c][d]. I think something like this can be done with numpy, but for the types of arrays that I'm using, numpy is not suitable, so I want to do it with python lists.
How can I have something like the above?
Edit: For a specific example of what I'm trying to achieve, see the demo in Martijn's answer.
You can use the reduce() function to access consecutive elements:
from functools import reduce # forward compatibility
import operator
reduce(operator.getitem, indices, somelist)
In Python 3 reduce was moved to the functools module, but in Python 2.6 and up you can always access it in that location.
The above uses the operator.getitem() function to apply each index to the previous result (starting at somelist).
Demo:
>>> import operator
>>> somelist = ['index0', ['index10', 'index11', ['index120', 'index121', ['index1220']]]]
>>> indices = [1, 2, 2, 0]
>>> reduce(operator.getitem, indices, somelist)
'index1220'
Something like this?
def get_element(lst, indices):
if indices:
return get_element(lst[indices[0]], indices[1:])
return lst
Test:
get_element([[["element1"]], [["element2"]], "element3"], [2])
'element3'
get_element([[["element1"]], [["element2"]], "element3"], [0, 0])
['element1']
Or if you want an iterative version:
def get_element(lst, indices):
res = lst
for index in indices:
res = res[index]
return res
Test:
get_element([[["element1"]], [["element2"]], "element3"], [1, 0])
['element2']

Python. How to optimize search functions

There any way to optimize these two functions ?
first function:
def searchList(list_, element):
for i in range (0,len(list_)):
if(list_[i] == element):
return True
return False
second function:
return_list=[]
for x in list_search:
if searchList(list_users,x)==False:
return_list.append(x)
Yes:
return_list = [x for x in list_search if x not in list_users]
The first function basically checks for membership, in which case you could use the in keyword. The second function can be reduced to a list comprehension to filter out elements from list_search list based on your condition.
For first function
def searchList(list, element):
return element in list
You can make it in 1 line
searchList = lambda x,y: y in x
For 2nd, use a list comp like shown in the other answer
What you are doing with your two functions is building the complement as ozgur pointed out.
Using sets is the most easy thing here
>>> set([2,2,2,3,3,4])- set([1,2,2,4,5])
set([3])
your list_search would be the first list and your list_users the second list.
The only difference is that your new user is only once in the result no matter how often it is in the list_search
Disclaimer: I assumed list_search has no duplicate elements. Otherwise, use this solution.
What you want is exactly the set complement of list_users in list_search.
As an alternative approach, you can use sets to get the difference between two lists and I think it should be much more performant than the naive look up which takes 0(n^2).
>>> list_search = [1, 2, 3, 4]
>>> list_users = [4, 5, 1, 6]
>>> print set(list_search).difference(list_users)
>>> {2, 3}

Is there a 'foreach' function in Python 3?

When I meet the situation I can do it in javascript, I always think if there's an foreach function it would be convenience. By foreach I mean the function which is described below:
def foreach(fn,iterable):
for x in iterable:
fn(x)
they just do it on every element and didn't yield or return something,i think it should be a built-in function and should be more faster than writing it with pure Python, but I didn't found it on the list,or it just called another name?or I just miss some points here?
Maybe I got wrong, cause calling an function in Python cost high, definitely not a good practice for the example. Rather than an out loop, the function should do the loop in side its body looks like this below which already mentioned in many python's code suggestions:
def fn(*args):
for x in args:
dosomething
but I thought foreach is still welcome base on the two facts:
In normal cases, people just don't care about the performance
Sometime the API didn't accept iterable object and you can't rewrite its source.
Every occurence of "foreach" I've seen (PHP, C#, ...) does basically the same as pythons "for" statement.
These are more or less equivalent:
// PHP:
foreach ($array as $val) {
print($val);
}
// C#
foreach (String val in array) {
console.writeline(val);
}
// Python
for val in array:
print(val)
So, yes, there is a "foreach" in python. It's called "for".
What you're describing is an "array map" function. This could be done with list comprehensions in python:
names = ['tom', 'john', 'simon']
namesCapitalized = [capitalize(n) for n in names]
Python doesn't have a foreach statement per se. It has for loops built into the language.
for element in iterable:
operate(element)
If you really wanted to, you could define your own foreach function:
def foreach(function, iterable):
for element in iterable:
function(element)
As a side note the for element in iterable syntax comes from the ABC programming language, one of Python's influences.
Other examples:
Python Foreach Loop:
array = ['a', 'b']
for value in array:
print(value)
# a
# b
Python For Loop:
array = ['a', 'b']
for index in range(len(array)):
print("index: %s | value: %s" % (index, array[index]))
# index: 0 | value: a
# index: 1 | value: b
map can be used for the situation mentioned in the question.
E.g.
map(len, ['abcd','abc', 'a']) # 4 3 1
For functions that take multiple arguments, more arguments can be given to map:
map(pow, [2, 3], [4,2]) # 16 9
It returns a list in python 2.x and an iterator in python 3
In case your function takes multiple arguments and the arguments are already in the form of tuples (or any iterable since python 2.6) you can use itertools.starmap. (which has a very similar syntax to what you were looking for). It returns an iterator.
E.g.
for num in starmap(pow, [(2,3), (3,2)]):
print(num)
gives us 8 and 9
The correct answer is "python collections do not have a foreach". In native python we need to resort to the external for _element_ in _collection_ syntax which is not what the OP is after.
Python is in general quite weak for functionals programming. There are a few libraries to mitigate a bit. I helped author one of these infixpy
pip install infixpy https://pypi.org/project/infixpy/
from infixpy import Seq
(Seq([1,2,3]).foreach(lambda x: print(x)))
1
2
3
Also see: Left to right application of operations on a list in Python 3
Here is the example of the "foreach" construction with simultaneous access to the element indexes in Python:
for idx, val in enumerate([3, 4, 5]):
print (idx, val)
Yes, although it uses the same syntax as a for loop.
for x in ['a', 'b']: print(x)
This does the foreach in python 3
test = [0,1,2,3,4,5,6,7,8,"test"]
for fetch in test:
print(fetch)
Look at this article. The iterator object nditer from numpy package, introduced in NumPy 1.6, provides many flexible ways to visit all the elements of one or more arrays in a systematic fashion.
Example:
import random
import numpy as np
ptrs = np.int32([[0, 0], [400, 0], [0, 400], [400, 400]])
for ptr in np.nditer(ptrs, op_flags=['readwrite']):
# apply random shift on 1 for each element of the matrix
ptr += random.choice([-1, 1])
print(ptrs)
d:\>python nditer.py
[[ -1 1]
[399 -1]
[ 1 399]
[399 401]]
If I understood you right, you mean that if you have a function 'func', you want to check for each item in list if func(item) returns true; if you get true for all, then do something.
You can use 'all'.
For example: I want to get all prime numbers in range 0-10 in a list:
from math import sqrt
primes = [x for x in range(10) if x > 2 and all(x % i !=0 for i in range(2, int(sqrt(x)) + 1))]
If you really want you can do this:
[fn(x) for x in iterable]
But the point of the list comprehension is to create a list - using it for the side effect alone is poor style. The for loop is also less typing
for x in iterable: fn(x)
I know this is an old thread but I had a similar question when trying to do a codewars exercise.
I came up with a solution which nests loops, I believe this solution applies to the question, it replicates a working "for each (x) doThing" statement in most scenarios:
for elements in array:
while elements in array:
array.func()
If you're just looking for a more concise syntax you can put the for loop on one line:
array = ['a', 'b']
for value in array: print(value)
Just separate additional statements with a semicolon.
array = ['a', 'b']
for value in array: print(value); print('hello')
This may not conform to your local style guide, but it could make sense to do it like this when you're playing around in the console.
In short, the functional programming way to do this is:
def do_and_return_fn(og_fn: Callable[[T], None]):
def do_and_return(item: T) -> T:
og_fn(item)
return item
return do_and_return
# where og_fn is the fn referred to by the question.
# i.e. a function that does something on each element, but returns nothing.
iterable = map(do_and_return_fn(og_fn), iterable)
All of the answers that say "for" loops are the same as "foreach" functions are neglecting the point that other similar functions that operate on iters in python such as map, filter, and others in itertools are lazily evaluated.
Suppose, I have an iterable of dictionaries coming from my database and I want to pop an item off of each dictionary element when the iterator is iterated over. I can't use map because pop returns the item popped, not the original dictionary.
The approach I gave above would allow me to achieve this if I pass lambda x: x.pop() as my og_fn,
What would be nice is if python had a built-in lazy function with an interface like I constructed:
foreach(do_fn: Callable[[T], None], iterable: Iterable)
Implemented with the function given before, it would look like:
def foreach(do_fn: Callable[[T], None], iterable: Iterable[T]) -> Iterable[T]:
return map(do_and_return_fn(do_fn), iterable)
# being called with my db code.
# Lazily removes the INSERTED_ON_SEC_FIELD on every element:
doc_iter = foreach(lambda x: x.pop(INSERTED_ON_SEC_FIELD, None), doc_iter)
No there is no from functools import foreach support in python. However, you can just implement in the same number of lines as the import takes, anyway:
foreach = lambda f, iterable: (*map(f, iterable),)
Bonus:
variadic support: foreach = lambda f, iterable, *args: (*map(f, iterable, *args),) and you can be more efficient by avoiding constructing the tuple of Nones

Categories