Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I want to try the many ways the function of python
So, I want to not use zip use other python function ,how can i do to?
this is use zip and adding more than one list:
but i want to other way not use zip:
x = [12, 22, 32, 42, 52, 62, 72, 82, 29]
y = [10, 11, 12, 13, 14, 15, 16, 17, 18]
def add_list(i, j):
l = []
for n, m in zip(x, y):
l.append(n + m)
return l
i know this way,
without using zip, you can use map:
from operator import add
x = [12, 22, 32, 42, 52, 62, 72, 82, 29]
y = [10, 11, 12, 13, 14, 15, 16, 17, 18]
res = map(add, x, y)
# [22, 33, 44, 55, 66, 77, 88, 99, 47]
Note that if the iterables are of different lengths, than the shortest will be padded with None which will cause a TypeError in the add instead of zip which will truncate to the shortest list.
On an aside there's absolutely nothing wrong with using zip - I'd probably re-write it as a list-comp though, eg:
[sum(items) for items in zip(x, y)]
This then scales easily to doing zip(x, y, z, another_list) etc...
oh, there are plenty of possibilities, here are a few:
# most simple way
res = []
for i in range(len(x)):
res.append(x[i]+y[i])
# this is the same as
res = [x[i]+y[i] for i in range(len(x))]
# more pythonic
from operator import add
res = map(add, x, y)
# less pytonic
res = map(int.__add__, x, y)
# using numpy
import numpy as np
res = list(np.array(x) + np.array(y))
# alternatively
res = list(np.add(x, y))
# also
res = list(np.sum([x,y], axis=0))
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Is there a quick way that doesn't involve a bunch of if-statements to get the first element in a list that my variable isn't bigger than? For example, if
x = 50
compare = [1, 4, 9, 16, 25, 36, 49, 64, 81]
I want this to return 64. My list will also be written in increasing order, so not every element in the list will need to be compared.
There's a short way of doing this that doesn't involve any for loop:
>>> x = 50
>>> compare = [1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> next(item for item in compare if item >=x)
64
This creates an iterator of values that are >= x, and then selects the first one.
Use a loop. Test each element, and break out of the loop when you find what you're looking for.
result = None
for el in compare:
if x < el:
result = el
break
if result is not None:
print('Found', result)
else:
print('Not found')
Here is a solution with numpy:
import numpy as np
x = 50
compare = np.array([1, 4, 9, 16, 25, 36, 49, 64, 81] )
compare[compare>=x][0]
I would use a while loop:
count = 0
while x < compare[count]:
count += 1
print(compare[count])
I had a job interview today. During it I was asked to write down an algorithm that will reverse a list. First I offered the answer using the reversed() method:
x = [1,2,3,4,5]
y = reversed(x)
for i in y:
print i
The senior developer conducting the interview asked me if I know another way, upon which I wrote down the other known method with slicing:
x = [1,2,3,4,5]
y = x[::-1]
Unfortunately he was unhappy with this solution as well and asked me to think of another one. After few minutes I said I could not come up with a better one. He said that this was not good enough for their standards.
I am perfectly fine with his opinion and have no problem practicing more on my code. My question is, what is a better solution that I am not aware of, if there is one. Could there be some other more 'programmer' way...Only other thing that comes to mind is recursion, however I thought of it only after the interview was already done.
Thanks.
Both your answers are good in terms of python so the interviewer must have been asking you to implement your own method:
Using recursion:
def recur_rev(l):
return recur_rev(l[1:]) + l[:1] if l else l
Or a list comp and range starting at the length of l -1 and going in reverse:
l = list(range(100))
print([l[ind] for ind in range(len(l)-1,-1,-1)])
Using itertools.count:
from itertools import count
cn = count(len(l) -1, -1)
print([l[next(cn)] for ele in l])
For efficiency use a generator expression:
rev = (l[next(cn)] for ele in l)
for ele in rev:
print(ele)
Or using map:
print(list(map(l.__getitem__,range(len(l)-1,-1,-1)))) # list needed for python3
[99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
without the list call on map we will get a map object we can iterate over in python3, you can use itertools.imap in python2 to achieve a similar result
I guess your interviewer wanted to hear something like this:
A straightforward way to revert a list is to find out its length, then iterate from len-1 downto 0 and append the i-th element to the result. This approach works fine with real lists, but how can we revert a generator, i.e. something whose length is not known and cannot be found? (Good pythonistas use generators and yields instead of lists and returns).
Here's where we need a data structure known as "stack". A stack is like, well, a stack of things, like plates, put on the top of each other.
Whatever you put last comes out first, whatever was put first comes out last. So, our strategy will be like this:
while there are items, put each item onto the stack
while the stack is not empty, pop items off the stack and return them
Stacks can be programmed in python using lists, where .append puts an item on the top of the stack, and .pop removes the last thing off the stack:
def reverse(it):
stack = []
for item in it:
stack.append(item)
while stack:
yield stack.pop()
Of course, Python already has a built-in stack, and it's the stack of call frames. We can use that instead of the simulated one above, which leads us to the following recursive solution:
def reverse(it):
head = next(it)
for item in reverse(it):
yield item
yield head
in python3, this is even more elegant:
def reverse(it):
head = next(it)
yield from reverse(it)
yield head
Again, this works with arbitrary iterables, whose length is unknown at the call time.
One simple algorithm that could be easily ported to other languages would be:
x = [1,2,3,4,5]
y = []
for i in len(x):
y.append(x[len(x) - 1 - i])
Or using an iterator. This could be easily ported to be used with a chained list where you don't know the length:
x = [1,2,3,4,5]
y = []
x_iterator = iter(x)
try:
while (1):
y.insert(0, x_iterator.next())
except:
print y
Or a more pythonic version with insert:
x = [1,2,3,4,5]
y = []
for elem in x:
y.insert(0, elem)
I'm assuming your interviewer didn't want you to use built-in Python methods, but an algorithm that's more language-agnostic. Something like:
lst = [1,2,3,4,5]
lst2 = []
while len(lst) > 0:
lst2.append(lst.pop())
or
lst2 = [lst.pop() for _ in lst[:]]
How about something like that:
x = [1, 2, 3, 4, 5]
for i in xrange(len(x) / 2):
x[i], x[-i - 1] = x[-i - 1], x[i]
print(x)
The idea is to swap array elements from opposite directions
I like this way:
def reverse(arr):
for i in range(len(arr) / 2):
arr[-i-1], arr[i] = arr[i], arr[-i-1]
Basically iterating through the first half of the array and swapping i and len(i)-i-1.
def reverse(text):
rev = []
for let in range(len(text),0,-1):
rev.append(text[let-1])
return ''.join(rev)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have two list of numbers but I need a evaluate and see if any numbers match then out put the # of matching numbers.
import random
matches = random.sample (range(1, 20), 5),random.sample (range(1, 20), 5)
You might be able to use a set intersection.
from random import sample
set_a = set(sample(range(0, 50), 10))
set_b = set(sample(range(0, 50), 10))
print set_a.intersection(set_b) # [3, 4]
print set_a & set_b # sugar for the same thing
list comprehension one liner:
[x for x in list_a if x in list_b]
you get the list of items contained in both lists.
to demonstrate all items are found:
>>> a = range(10,50)
>>> b = range(10,50)
>>> [x for x in a if x in b]
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
From what I understood from your code I came up with following code. Let me know if this helped you
m = [1,2,3]
n = [3,4,1]
for i in m:
for j in n:
if i == j:
print "matched elements are list1 and list2 are (%s) and (%s)" %(i,j)
else:
print "list1 and list2 have unique elements"
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to make a function that takes a string as input and outputs a list of all numerical values.
Some examples:
"22-28, 31-35, 37" should output: [22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 37]
"22, 24" should output: [22, 24]
"23" should output: [23]
How can I do this?
Try regular expressions.
import re
r = re.findall('[0-9]+-[0-9]+|[0-9]+',string)
ans = []
for i in r:
if '-' in i:
t = i.split('-')
ans.extend(range(int(t[0]),int(t[1])))
else:
ans.append(int(i))
print ans
Without regular expressions:
def text_range(s):
res = []
for pc in s.split(','):
if '-' in pc: # this assumes no negative numbers in the list!
a,b = [int(i) for i in pc.split('-')]
res.extend(range(a, b+1))
else:
res.append(int(pc))
return res
then
text_range("22-28, 31-35, 37") # -> [22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 37]
First off, there isn't a question if you break this problem into three steps: 1) create some_list 2) create random_list and 3) run a straight forward list comprehension over the two lists (i.e. [(x, y, f(y, m)) for x in l for y in m]. Because of the constraints of some APIs I am working with, I want be able to write the code with two lines: 1) create some_list 2) run a list comprehension which creates the second second list and allows for some operation/function/method against the internally generated list itself.
This is what I would like to be able to do:
import random
[(x, y, not random_list.index(y)) for x in some_list
for y in random.sample([1,2,3,4,5], (random.choice([1,2,3]))) as random_list]
I know the as random_list doesn't work here. I know if I create a list based on random.sample([1,2,3,4,5], random.choice([1,2,3])) before I code the list comprehension, there isn't any problem here.
Writing out the question leads to some answers. Here is the specific answer to the specific problem given above:
[(x, y, not i) for x in some_list
for i, y in enumerate(random.sample([1,2,3,4,5], random.choice([1,2,3])))]
My basic question is: if a list is created inside a list comprehension, can that list itself be referenced within the list comprehension? Or do I need to create some kind of wrapper?
def wrapper():
f = lambda i, l: 42
l = random_list()
return [(i, f(i, l)) for i in l]
[(x, i, v) for x in some_list for i, v in wrapper()]
I think I have largely answered my question, but it seemed like a good one worth writing up. If there are other thoughts, comments, that would be very useful.
#DSM valid question. Here is the particular (django) code:
PlayerPosition.objects.bulk_create([
PlayerPosition(
player=player,
position_id=position_id,
primary=not index
) for player in Player.objects.all()
for index, position_id in enumerate(random_position_list())
])
Essentially you want to create a list, bind it to a name, and then use the name inside a list comprehension. What prevents binding a name in an expression is that assignments are statements. However, you can (ab)use lambdas to get what you want:
(lambda random_list: [
(x, y, not random_list.index(y))
for x in some_list
for y in random_list])(
random_list=random.sample([1, 2, 3, 4, 5], random.choice([1, 2, 3])))
That works in that it's one line of code, but I'm not sure if it works within your other constraints, which are at this point enigmatic and unclear.
EDIT: If you can make a helper function then you should almost certainly take that approach. I would do it differently than yours, though. I'd make a generic one like this:
def iter_with_list(l):
for element in l:
yield (l, element)
Using it like so:
[(x, y, not random_list.index(y))
for x in some_list
for random_list, y in iter_with_list(random.sample([1,2,3,4,5], random.choice([1, 2, 3])))]
That way you can still keep all the logic in the comprehension without spreading it all over the place. This is just another trick to bind a name as part of an expression - in this case by repeatedly offering it up to be bound for each iteration of the comprehension - but it's a lot more elegant than the previous one.
My basic question is: if a list is created inside a list comprehension, can that list itself be referenced within the list comprehension?
Short answer is, yes it can. You can have as many list comprehensions inside list comprehensions as you like, but things will get quite unreadable. Demonstration:
>>> [var for var in [val for val in range(1, 100)]]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>>
If you want to combine two lists, as tuples:
You can do something like this:
>>> from random import randint
>>> zip([x for x in xrange(0, 10)], [randint(0, 100) for _ in xrange(10)])
[(0, 56), (1, 60), (2, 7), (3, 29), (4, 85), (5, 76), (6, 95), (7, 91), (8, 40), (9, 4)]
You can even apply operations on the values of list comprehensions (but it gets really unreadable then):
>>> weird_list = [val for val in [var for var in xrange(0, 100) if not var % 2] if not val % 3]
>>> print weird_list
[0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96]
With regard to your comment:
>>> another_weird_list = [(var, 42) for var in xrange(5)]
>>> another_weird_list
[(0, 42), (1, 42), (2, 42), (3, 42), (4, 42)]
No need for a lambda.
In response to your second comment:
Initially:
arbitrary_list = [x for x in range(10)]
f = lambda x: [var + 1 for var in x]
no_list = [(var, f(arbitrary_list)) for var in arbitrary_list]
Then:
no_list = [(var, [var + 1 for var in [x for x in range(10)]]) for var in [x for x in range(10)]]
One liner. You can still make an arbitrary_list if you want.