Creating two lists and compare the matching [closed] - python

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"

Related

Is there a problem to use list.remove while iterating? [duplicate]

I've got this piece of code:
numbers = list(range(1, 50))
for i in numbers:
if i < 20:
numbers.remove(i)
print(numbers)
but the result I'm getting is:
[2, 4, 6, 8, 10, 12, 14, 16, 18, 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]
Of course, I'm expecting the numbers below 20 to not appear in the results. Looks like I'm doing something wrong with the remove.
You're modifying the list while you iterate over it. That means that the first time through the loop, i == 1, so 1 is removed from the list. Then the for loop goes to the second item in the list, which is not 2, but 3! Then that's removed from the list, and then the for loop goes on to the third item in the list, which is now 5. And so on. Perhaps it's easier to visualize like so, with a ^ pointing to the value of i:
[1, 2, 3, 4, 5, 6...]
^
That's the state of the list initially; then 1 is removed and the loop goes to the second item in the list:
[2, 3, 4, 5, 6...]
^
[2, 4, 5, 6...]
^
And so on.
There's no good way to alter a list's length while iterating over it. The best you can do is something like this:
numbers = [n for n in numbers if n >= 20]
or this, for in-place alteration (the thing in parens is a generator expression, which is implicitly converted into a tuple before slice-assignment):
numbers[:] = (n for in in numbers if n >= 20)
If you want to perform an operation on n before removing it, one trick you could try is this:
for i, n in enumerate(numbers):
if n < 20 :
print("do something")
numbers[i] = None
numbers = [n for n in numbers if n is not None]
Begin at the list's end and go backwards:
li = list(range(1, 15))
print(li)
for i in range(len(li) - 1, -1, -1):
if li[i] < 6:
del li[i]
print(li)
Result:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
[6, 7, 8, 9, 10, 11, 12, 13, 14]
#senderle's answer is the way to go!
Having said that to further illustrate even a bit more your problem, if you think about it, you will always want to remove the index 0 twenty times:
[1,2,3,4,5............50]
^
[2,3,4,5............50]
^
[3,4,5............50]
^
So you could actually go with something like this:
aList = list(range(50))
i = 0
while i < 20:
aList.pop(0)
i += 1
print(aList) #[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]
I hope it helps.
The ones below are not bad practices AFAIK.
EDIT (Some more):
lis = range(50)
lis = lis[20:]
Will do the job also.
EDIT2 (I'm bored):
functional = filter(lambda x: x> 20, range(50))
So I found a solution but it's really clumsy...
First of all you make an index array, where you list all the index' you want to delete like in the following
numbers = range(1, 50)
index_arr = []
for i in range(len(numbers):
if numbers[i] < 20:
index_arr.append(i)
after that you want to delete all the entries from the numbers list with the index saved in the index_arr. The problem you will encounter is the same as before. Therefore you have to subtract 1 from every index in the index_arr after you just removed a number from the numbers arr, like in the following:
numbers = range(1, 50)
index_arr = []
for i in range(len(numbers):
if numbers[i] < 20:
index_arr.append(i)
for del_index in index_list:
numbers.pop(del_index)
#the nasty part
for i in range(len(index_list)):
index_list[i] -= 1
It will work, but I guess it's not the intended way to do it
As an additional information to #Senderle's answer, just for records, I thought it's helpful to visualize the logic behind the scene when python sees for on a "Sequence type".
Let's say we have :
lst = [1, 2, 3, 4, 5]
for i in lst:
print(i ** 2)
It is actually going to be :
index = 0
while True:
try:
i = lst.__getitem__(index)
except IndexError:
break
print(i ** 2)
index += 1
That's what it is, there is a try-catch mechanism that for has when we use it on a Sequence types or Iterables(It's a little different though - calling next() and StopIteration Exception).
*All I'm trying to say is, python will keep track of an independent variable here called index, so no matter what happens to the list (removing or adding), python increments that variable and calls __getitem__() method with "this variable" and asks for item.
Building on and simplying the answer by #eyquem ...
The problem is that elements are being yanked out from under you as you iterate, skipping numbers as you progress to what was the next number.
If you start from the end and go backwards, removing items on-the-go won't matter, because when it steps to the "next" item (actually the prior item), the deletion does not affect the first half of the list.
Simply adding reversed() to your iterator solves the problem. A comment would be good form to preclude future developers from "tidying up" your code and breaking it mysteriously.
for i in reversed(numbers): # `reversed` so removing doesn't foobar iteration
if i < 20:
numbers.remove(i)
You could also use continue to ignore the values less than 20
mylist = []
for i in range(51):
if i<20:
continue
else:
mylist.append(i)
print(mylist)
Since Python 3.3 you may use the list copy() method as the iterator:
numbers = list(range(1, 50))
for i in numbers.copy():
if i < 20:
numbers.remove(i)
print(numbers)
[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]

Python: Finding strings in a list containing an interval and replacing this interval by every number in it

I'm wondering if there's any beautiful/clean way of doing what I'm trying to :).
(I'm sure there is)
So My function receives a list of strings that can either contains strings in 2 format:
"12,13,14,15" or "12 to 15"
The goal is to parse the second type and replace the "to" by the numbers in the interval.
Delimiters between numbers doesn't matter, a regex will do the job after.
Here is pseudo code and an ugly implementation
The idea is to replace "to" in the list by the numbers in the interval so that I can easily parse numbers with a regex afterwards
# The list is really inconsistent, separators may change and it's hand filled so some comments like in the last example might be present
l = ["12,13,14,15",
"12 to 18",
"10,21,22 to 42",
"14,48,52",
"12,14,22;45 and also 24 to 32"
]
def process_list(l):
for x in l:
if "to" in x:
# Find the 2 numbers around the to and replace the "to" by ",".join(list([interval of number]))
final_list = numero_regex.findall(num)
return final_list
I think you don't need regex:
def process_list(l):
final_list = []
for s in l:
l2 = []
for n in s.split(','):
params = n.split(' to ')
nums = list(range(int(params[0]), int(params[-1])+1))
l2.extend(nums)
final_list.append(l2)
return final_list
Output:
>>> process_list(l)
[[12, 13, 14, 15],
[12, 13, 14, 15, 16, 17, 18],
[10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42],
[14, 48, 52]]
Update:
I wanted an output for this case like this ["12,21,32;14, and the 12,13,14,15,[...],40"]. Which I can really easily parse with a regex
If you just want to replace 'number1 to number2', you can do:
def process_list(l):
def to_range(m):
return ','.join([str(i) for i in range(int(m.group('start')),
int(m.group('stop'))+1)])
return [re.sub(pat, to_range, s) for s in l]
Output:
# l = ["12,21,18 to 20;32;14, and the 12 to 16"]
>>> process_list(l)
['12,21,18,19,20;32;14, and the 12,13,14,15,16']
Here is one solution:
from itertools import chain
def split(s):
return list(chain(*(list(range(*list(map(int, x.split(' to ')))))+[int(x.split(' to ')[1])]
if ' to ' in x else
[int(x)]
for x in s.split(',')
)))
[split(e) for e in l]
output:
[[12, 13, 14, 15],
[12, 13, 14, 15, 16, 17, 18],
[10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42],
[14, 48, 52]]
edit: I adapted the above solution to be used with regexex:
from itertools import chain
def split(s):
regex = re.compile('(\d+\s*to\s*\d+|\d+)')
return list(chain(*([int(x)] if x.isnumeric() else
list(range(*map(int, re.split('\s+to\s+', x))))
+[int(re.split('\s+to\s+', x)[-1])]
for x in regex.findall(s)
)))

Adding more than one list [closed]

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))

Get numerical values from string input in Python [closed]

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]

How to find the two indexes from a list whos values are closest to zero

I'm working on a piece for my GA (fitness calculation actually) and I need to get the indexes of two values from a list whos values are closest to zero. I have been looking for about an hour all over the internet and though it seems I have become extremely close, and it looks like it should work, testing with print statements show that my code isnt working..
My process right now is:
Find the closest index and store it
Delete it from original array
Find the new closest
this is the code in question:
closest = min(range(len(fitness_levels)), key=lambda i: abs(fitness_levels[i]-0))
fitness_levels.pop(closest)
second_closest = min(range(len(fitness_levels)), key=lambda i: abs(fitness_levels[i]-0))
when fitness_levels = [-20, 23, -55, 11, 10, -18, -48, 16, -60, 20, 22, 16, 21, 66, 10, 46, -42] granted those numbers are generated completely at random.
Like I said, when i do some checking with print statements i find this method doensnt work in multiple ways, at one point i even ended up with the same index different values. Does anyone have a better workable way to do this? - python 2.7.x
Side note- i come from a php background, still warming up to python, so some syntax could be wrong...
While sorting with an abs key would work, that's an nlogn solution. Here's a linear solution
fitness_levels = [-20, 23, -55, 11, 10, -18, -48, 16, -60, 20, 22, 16, 21, 66, 10, 46, -42]
a,b = sorted(fitness_levels[:2], key=abs) # setting defaults. a<=b
ia, ib = 0,1 # indices
for i,val in enumerate(fitness_levels[2:]): # use itertools.islice for large lists (for constant space)
if abs(val) < abs(a):
b,a = a,val
ib, ia = ia, i
elif abs(val) < abs(b):
b = val
ib = i
I'd go for:
fitness_levels = [-20, 23, -55, 11, 10, -18, -48, 16, -60, 20, 22, 16, 21, 66, 10, 46, -42]
import heapq
closest2 = heapq.nsmallest(2, ((abs(val), idx) for idx, val in enumerate(fitness_levels)))
# [(10, 4), (10, 14)]
indices = [el[1] for el in closest2]
# [4, 14]
Something like this:
>>> lis = [-20, 23, -55, 11, 10, -18, -48, 16, -60, 20, 22, 16, 21, 66, 10, 46, -42]
for i,x in enumerate(sorted(enumerate(lis), key=lambda x:abs(0 - x[1]))[:2]):
x = list(x)
x[0] -= i #reduce index as an item was removed from the list
ind, val = x
print "{}->{}".format(ind, val)
...
4->10
13->10
If you don't want index to be decreased then simply this is enough:
>>> sorted(enumerate(lis), key=lambda x:abs(0-x[1]))[:2]
[(4, 10), (14, 10)]
How about:
>>> from numpy import argsort,abs
>>> fitness_levels = [-20,23,-55,11,10,-18,-48,16,-60,20,22,16,21,66,10,46,-42]
>>> i,j = argsort(abs(fitness_levels))[:2]
>>> print (i,fitness_levels[i]),(j,fitness_levels[j])
>>> (14 10) (4 10)

Categories

Resources