I have this exercise from a list, return two list's one with positive numbers and the other with negative.
My code:
def fuc(list):
negatives = []
positives = []
for i in list:
if i > 0:
positives.append(i)
print(i)
else:
negatives.append(i)
print(i)
print(fuc([1,-1,2,-2,3,-3,4,-4,5,-5]))
This code doesn't return 2 list's(negative and positive), I want to know how I get 2 list's from the original list.
Adding the else keyword and returning the values would work, but there's a nicer approach using ternary expression to determine which list to append to:
def func(l):
negatives = []
positives = []
for i in l:
(positives if i >= 0 else negatives).append(i):
return negatives,positives
That is, if you consider 0 as positive, else you'd have to filter it out and the interest would be limited.
If you have the choice of using numpy you can do something like this.
import numpy as np
def fuc(myList):
myList=np.array(myList)
neg=myList[np.less(myList,0)]
pos=myList[np.greater(myList,0)]
return list(neg),list(pos)
Related
I have the following funciton telling us that a series has at least one negative value:
def has_negative(series):
v=False
for i in range(len(series)):
if series[i]<0:
v=True
break
return v
When we use this function on an example we get :
y=[1,2,3,4,5,6,7,8,9]
z=[1,-2,3,4,5,6,7,8,9]
print(has_negative(y))
print(has_negative(y))
Output:
>>> False
>>> True
The function seems to work well, although I want to make it shorter, any suggestion from your side will be appreciated
You can utilise the built-in any function as follows:
def has_negative(lst):
return any(e < 0 for e in lst)
print(has_negative([1,2,3,4,5,6,7,8,9]))
print(has_negative([1,-2,3,4,5,6,7,8,9]))
Output:
False
True
EDIT:
Did some timing tests based around this and other suggested answers. Whilst this is concise and functionally correct, it doesn't perform well. Keep it simple and use #quamrana's first suggestion - it's much faster
You can sort the list and get the first element, check if it's a negative. With this approach you don't have to iterate over the array:
sorted(series)[0] < 0
There are several improvements you can make:
def has_negative(series):
for i in series:
if i < 0:
return True
return False
or it can be contracted into one line like this:
print(bool([i for i in z if i<0]))
To add:
To keep it clean and short, you could also use a list comprehension within a lambda function as follows:
has_negative = lambda series: True if [series for x in series if x < 0] else False
z = [1,-2,3,4,5,6,7,8,9]
has_negative(z)
Output:
>>> True
This is working fine but I just don't get it why this works in this way. I think the return of True value should be inside the for loop but when I run this program it works in the opposite way.
Can someone point out what i am misunderstanding about the indentation of return values?
Even though the solution was even shorter I wanted to know exactly about my way of coding. Please help!
# My attempt
def palindrome(s):
mylist = list(s)
j = -1
for i in range(0,len(mylist)-1):
if mylist[i] == mylist[j]:
i+=1
j-=1
continue
return False
return True
# Solution answer:
def palindrome(s):
return s == s[::-1]
When a function is called, the function can return only once.
This kind of return pattern is very frequently found across various programming languages. It is intuitive and efficient.
Let's say you have to check if a list of 1000 values contain only even numbers. You loop through the list and check if each element is even. Once you find an odd number, you do not need to go further. So you efficiently and immediately return and exit from the loop.
Here is hopefully a little bit more intuitive version of your code:
def palindrome(s):
l, r = -1, 0 # left, right
for _ in range(0, len(s) // 2 + 1): # more efficient
l += 1
r -= 1
if s[l] != s[r]:
return False
return True
Once you know the input is not palindrome, you do not need to go further.
If you did not need to stop, it is palindrome.
They follow the exact same rules as any other statement. What you have written means
def palindrome(s) {
mylist = list(s)
j = -1
for i in range(0,len(mylist)-1) {
if mylist[i] == mylist[j] {
i+=1
j-=1
continue
}
return False
}
return True
}
# My attempt
def palindrome(s):
mylist = list(s)
j = -1
for i in range(0,len(mylist)-1):
if mylist[i] == mylist[j]:
i+=1
j-=1
continue
return False
return True
In the above code what happens is inside the for loop each time it checks if there is a mismatch in the values by comparing values by iterating over the list forwards using variable "i" and backwards using variable "j". and returns false immediately if any one letter mismatches and so exits from the loop. And true is returned only once the for loop is completed which means no mismatch was found in the loop
Note: i=0 gives first index, i+=1 iterates forward and j=-1 gives last index, j-=1 iterates backward
Basically, when you index an array in numpy, you do it the way:
a[start:end:step]
,for every dimension. If step is negative, you return the values in inverse order. So, if step is -1, the array a[::-1] is the inverted array of a[::].
a[::-1] = a[::]
Then, if a sequence is the same as its inverse, by definition, it is a palindrome.
See:
https://www.geeksforgeeks.org/numpy-indexing/
I'm trying to generate 20 random numbers in my list. Next I want to see if there are any repeated numbers in it.
I generated the random numbers. Next I did an insertion sort in order to arrange the list in a growing order. To see if I had any repeated numbers, I iterated over the list and if the previous number was equal to the next number, then my list had repeated numbers in it.
import random
random_array=[]
def array():
for i in range(0,20):
random_element=random.randint(1,35)
random_array.append(random_element)
return random_array
print(array())
# function to order the list
def insertion_sort():
for i in range(1,len(random_array)):
while i>0 and random_array[i-1]>random_array[i]:
random_array[i-1],random_array[i]=random_array[i],random_array[i-1]
i=i-1
return random_array
print(insertion_sort())
def verification():
for i in random_array:
insertion_sort()
if i-1==i:
return True
else:
return False
print(verification())
My program always returns false independent of the generated list.
Issues in your code:
You are iterating on the elements and subtracting them and comparing, instead you should iterate on the indexes and use them to compare consecutive elements
You are calling insertion_sort() within your for loop, I assume by mistake
You want to break the for loop on the first match you found, and in the end return a boolean which tells if the match has happened or not
So your code will look like
def verification():
#Flag to keep track of matches
flag = False
#Iterate over list via indexes
for i in range(len(random_array)):
#If consecutive elements match, set flag to true and break loop
if random_array[i-1]==random_array[i]:
flag = True
break
#Return flag value
return flag
You can do it with much shorter code using itertools.Counter:
import random
from collections import Counter
# Generate a random array
random_array = [random.randint(1, 35) for _ in range(20)]
nums = [
n # A number
for (n, count) in Counter(random_array).items() # From countered items
if count > 1 # If the count of this number is more than one
]
print(nums)
You have two options here: If you don't care about the order, you can use set which is a data type that can only have unique elements. If you need to keep your original order of numbers, you need to use OrderedDict from collections
See this stack answer: https://stackoverflow.com/a/7961393/11323304
Your verification function is wrong. You are comparing the value of element i to the value of element i - 1, which is never going to be true. Try this:
insertion_sort()
for i in range(1,len(random_array - 1)):
if random_arry[i] == random_array[i-1]:
return True
return False # If you get through every element without finding a match, return False
your loop in def verification(): is exiting after first iteration because if else: return False (it's exiting)
use simple flag:
import random
random_array=[]
def array():
for i in range(0,20):
random_element=random.randint(1,35)
random_array.append(random_element)
return random_array
print(array())
# function to order the list
def insertion_sort():
for i in range(1,len(random_array)):
while i>0 and random_array[i-1]>random_array[i]:
random_array[i-1],random_array[i]=random_array[i],random_array[i-1]
i=i-1
return random_array
print(insertion_sort())
def verification():
#for i in random_array:
status = False # <----
for i in range(len(random_array)-1): # <------
insertion_sort()
#if i-1==i:
if random_array[i] == random_array[i+1]: # Iterate over list by indexes
status = True
break
return status
print(verification())
I have a list:
l = [1,3,4,6,7,8,9,11,13,...]
and a number n.
How do I efficiently check if the number n can be expressed as the sum of two numbers (repeats are allowed) within the list l.
If the number is in the list, it does not count unless it can be expressed as two numbers (e.g for l = [2,3,4] 3 would not count, but 4 would.
This, embarrassingly, is what I've tried:
def is_sum_of_2num_inlist(n, num_list):
num_list = filter(lambda x: x < n, num_list)
for num1 in num_list:
for num2 in num_list:
if num1+num2 == n:
return True
return False
Thanks
def summable(n, l):
for v in l:
l_no_v = l[:]
l_no_v.remove(v)
if n - v in l_no_v:
return True
return False
EDIT: Explanation...
The itertools.cominations is a nice way to get all possible answers, but it's ~4x slower than this version since this is a single loop that bails out once it gets to a possible solution.
This loops over the values in l, makes a copy of l removing v so that we don't add v to itself (i.e. no false positive if n = 4; l = [2, 1]). Then subtract v from n and if that value is in l then there are two numbers that sum up to n. If you want to return those numbers instead of returning True just return n, n - v.
Although you can check this by running through the list twice, I would recommend for performance converting the list to a set, since x in set() searches in linear time.
Since n can be the sum of the same number, all you have to do is iterate through the set once and check if n - i occurs elsewhere in the set.
Something like the following should work.
>>> def is_sum_of_numbers(n, numbers):
... for i in numbers:
... if n - i in numbers:
... return True
... return False
...
>>>
>>>
>>> numbers = {2,7,8,9}
>>> is_sum_of_numbers(9, numbers) # 2 + 7
True
>>> is_sum_of_numbers(5, numbers)
False
>>> is_sum_of_numbers(18, numbers) # 9 + 9
True
If the list is ordered you could use two variables to go through the list, one starting at the beginning of the list and one at the end, if the sum of the two variables is greater than N you assign to the variable at the end the values that precedes it, if the sum is less than N you assign to the variable at the beginning the following value in the list. If the sum is N you've found the two values. You can stop when the two variables meet eachother.
If the list is not ordered you start from the beginning of the list and use a variable x to go through the list. You'll need another structure like an hashset or another structure. At every step you'll look up in the second hashset if the value N-x is in there. If there is, you've found the two numbers that add up to N. If there isn't you'll add N-x in the hashset and assign to x the following value. I recommend using an hashset because both the operations of looking up and inserting are O(1).
Both algorithms are linear
I'm sorry I couldn't write directly the code in python because I don't use it.
As I said in the comment HERE there's a video in wich your problem is solved
If I got the OP's concern then-
As the question says repeats are allowed within the list l this process i think is good though a bit slower.So if you need to count the occurances along with the existence of a condition then go with this answer but if you want a bolean esixtence check the go with the others for the mere performance issue nothing else.
You can use itertools.combinations. It will give you all the combinations, not permutations. Now you can just use the sum function to get the sum.
from itertools import combinations
l = [1,3,4,6,7,8,9,11,13]
checks = [4,6] #these are the numbers to check
for chk in checks:
for sm in combinations(l,2):
if chk == sum(sm): #sum(sm) means sum(1,3) for the first pass of the loop
#Do something
I've just started exploring the wonders of programming. I'm trying to write a code to identify numeric palindromes. Just looking at numbers and not texts. I'm trying to learn to use recursion here. But I'm just not getting anywhere and I can't figure out what's wrong with it.
My idea was to check first string vs the last, then delete these two if they match, and repeat. Eventually there'll be nothing left (implying it is a palindrome) or there will be a couple that doesn't match (implying the reverse).
I know there are better codes to finding palindromes in but I just wanted to try my hand at recursion.
So what's wrong?
def f(n):
global li
li=list(str(n))
if (len(li)==(1 or 0)):
return True
elif li[len(li)-1]==li[0]:
del li[0]
del li[len(li)-1]
if len(li)==0:
return True
if len(li)>0:
global x
x=''.join(li)
str(x)
f(x)
else:
return False
Thanks in advance!
A few comments
Why are x and li globals? In recursion, all variables should be local.
Why are you converting back and forth between str and list? You can subscript both of them
You need to return the result of your recursive call: return f(x)
Try these suggestions, and see how it works out.
Before looking into it too much, if (len(li)==(1 or 0)): doesn't do what you're expecting it to do. (1 or 0) will always evaluate to 1.
You probably want:
if len(li) in (1, 0):
There are a couple of problems with your solution. Let me analyse them line by line.
You don't need global statements if you don't intend to change variables outside of function scope. Thus, I removed two lines with global from your code.
li=list(str(n)): casting a string to a list is unnecessary, as a string in Python has a similar interface to an immutable list. So a simple li = str(n) will suffice.
if (len(li)==(1 or 0)):: although it looks OK, it is in fact an incorrect way to compare a value to a few other values. The or operator returns the first "true" value from its left or right operand, so in this case it always returns 1. Instead, you can use the in operator, which checks whether the left operand is an element of a right operand. If we make the right operand a tuple (1, 0), all will be well. Furthermore, you don't need parentheses around the if statement. You should write: if len(li) in (1, 0):
elif li[len(li)-1]==li[0]: is fine, but we can write this shorter in Python, because it supports negative list indexing: elif li[-1] == li[0]:
Because we don't use lists (mutable sequences) because of point 2., we can't do del li[0] on them. And anyway, removing the first element of a list is very inefficient in Python (the whole list must be copied). From the very same reason, we can't do del li[len(li)-1]. Instead, we can use the "splicing" operator to extract a substring from the string: li = li[1:-1]
if len(li)==0: is unnecessary long. In Python, empty strings and lists resolve to False if tested by an if. So you can write if not li:
if len(li)>0:: You don't have to check again if li is not empty -- you checked it in point 6. So a simple else: would suffice. Or even better, remove this line completely and unindent the rest of the function, because the body of the if in 6. contains a return. So if we didn't enter the if, we are in the else without writing it at all.
x=''.join(li): We don't need to convert our string to a string, because of the decision made in 2. Remove this line.
str(x): This line didn't do anything useful in your code, because str() doesn't modify its argument in place, but returns a new value (so x = str(x) would have more sense). You can also remove it.
f(x): This is a valid way to call a recursive function in Python, but you have to do something with its value. Return it perhaps? We'll change it to: return f(li) (as we don't have an x variable any more).
We end up with the following code:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
if not li:
return True
return f(li)
else:
return False
It's almost what we need, but still a little refinement can be made. If you look at the lines if not li: return True, you'll see that they are not necessary. If we remove them, then f will be called with an empty string as the argument, len(li) will equal 0 and True will be returned anyway. So we'll go ahead and remove these lines:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
return f(li)
else:
return False
And that's it! Good luck on your way to becoming a successful programmer!
Split the whole show out into a list, then just:
def fun(yourList):
if yourList.pop(0) == yourList.pop(-1):
if len(yourList) < 2:
return True # We're a palindrome
else:
return fun(yourList)
else:
return False # We're not a palindrome
print "1234321"
print fun(list("1234321")) # True
print "6234321"
print fun(list("6234321")) # False
def palindrome(n):
return n == n[::-1]
It's hard to tell what you intend to do from your code, but I wrote a simpler (also recursive) example that might make it easier for you to understand:
def is_palindrome(num):
s = str(num)
if s[0] != s[-1]:
return False
elif not s[1:-1]:
return True
else:
return is_palindrome(int(s[1:-1]))
number = int(raw_input("Enter a number: "))
rev = 0
neg = number
original = number
if (number < 0):
number = number * -1
else:
number = number
while ( number > 0 ):
k = number % 10
number = number / 10
rev = k + ( rev * 10 )
if (number < 1):
break
if ( neg < 0 ):
rev = ( rev * -1)
else:
rev = (rev)
if ( rev == original):
print "The number you entered is a palindrome number"
else:
print "The number you entered is not a palindrome number"
This code even works for the negative numbers i am new to programming in case of any errors
dont mind.