I have a 2D numpy.array, which should act as indices for another, so it should contain only ints or bools. Is there a quick and elegant (one line) way for checking for this condition?
I've tried the following code, but it does not provide the desired output, as it only checks for 0s and not for Nones, which is the value present in my case:
Example 1:
a = np.array([[1, 2, 3], [3, 4, 5]])
np.all(type(a) == np.int64, axis=0)
Current Output 1:
False
Example 2:
b = np.array([[1, 2, None], [3, 4, 5]])
np.all(type(a) == np.int64, axis=0)
Current Output 2:
False
so in the first example I'd like to get True as an output, as all the values of this array are numeric, while in example 2 - I'd like to get false, as there is a None value present in the first row of b array.
Appreciate any help.
This should work:
(b == None).any()
Returns true if any element of b is None.
Note that type(a) will return <class 'numpy.ndarray'> for any numpy array a. That is why your check always returns False irrespective of the presence of None.
You should check a.dtype for the getting the data type. That being said, any array that has None or strings in it will be of type object in numpy.
Example:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
a.dtype
# dtype('int64')
type(a)
# <class 'numpy.ndarray'>
(a == None).any()
# False
b = np.array([[1, 2, None], [3, 4, 5]])
b.dtype
# dtype('O')
type(b)
# <class 'numpy.ndarray'>
(b == None).any()
# True
(b == None).any(axis = 0)
# array([False, False, True])
(b == None).any(axis = 1)
# array([ True, False])
Related
Here is a task i got:
Cards are laid out on the table in a row, each card has a natural number written on it. In one move, it is allowed to take a card either from the left or from the right end of the row. In total, you can make k moves. The final score is equal to the sum of the numbers on the selected cards. Determine what is the maximum score you can get at the end of the game.
Here`s my code:
def card_counter(arr, k):
if len(arr) == k:
return sum(arr)
rang = len(arr) // 2
left = arr[:rang]
right = list(reversed(arr[rang:]))
c = 0
for _ in range(k):
min_arr = left if sum(left) >= sum(
right) and len(left) > 0 else right
c += min_arr.pop(0)
return c
if __name__ == '__main__':
assert card_counter([1, 2, 3, 4, 5], 5) == 15
assert card_counter([0, 0, 0], 1) == 0
assert card_counter([150], 1) == 150
This code works on all variants that I have come up with, including extreme cases. But the system does not accept this option, automatic tests do not pass. Where can there be a mistake?
I cannot comment on the algorithm you implemented as you did not state it in non-algorithm terms and I am not familiar with the language you are using (which I am guessing is Python). I will present a simple solution written in Ruby, hoping that the description I give will make it understood by readers who do not know Ruby.
Suppose
deck = [1, 2, 5, 7, 1, 4, 6, 3]
nbr_moves = 4
ds = deck.size
#=> 8
After removing nbr_moves from the ends,
m = ds - nbr_moves
#=> 4
consecutive cards will remain. In Ruby we could write
best = (0..ds-1).each_cons(m).max_by { |arr| deck.values_at(*arr).sum }
#=> [3, 4, 5, 6]
to obtain the indices of deck, for which the sum of the associated values is maximum:
deck.values_at(*best).sum
#=> 18
where
deck.values_at(*best)
#=> [7, 1, 4, 6]
In view of the value of best ([3, 4, 5, 6]), we need to remove left = best.first #=> 3 elements from the left and nbr_moves - left #=> 1 element from the right. The order of the removals is not relevant.
Note that
enum = (0..ds-1).each_cons(m)
#=> #<Enumerator: 0..7:each_cons(4)>
returns an enumerator. We can convert this enumerator to an array to see the values it will generate.
enum.to_a
#=> [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]
When, for example,
arr = [2, 3, 4, 5]
then
a = deck.values_at(*arr)
#=> [5, 7, 1, 4]
a.sum
#=> 17
Note that, having computed, for example,
t = [deck[i], deck[i+1],..., deck[j]].sum
the sum of
[deck[i+1], deck[i+2],..., deck[j+1]]
is seen to equal
t - deck[i] + deck[j+1]
This suggests a more efficient way to perform the calculations when m is large.
We have some objets (about 100,000 objects), each object has a property with some integers (range from 1 to 20,000, at most 20 elements, no duplicated elements.):
For example:
object_1: [1, 4]
object_2: [1, 3]
object_3: [100]
And the problem is, we input a array of integer (called A), find out which objects hold the subset of A.
For example:
when A = [1], the output should be []
when A = [1, 4], the output should be [object_1]
when A = [1, 3, 4], the output should be [object_1, object_2]
The problem can be described in python:
from typing import List
# problem description
class Object(object):
def __init__(self, integers):
self.integers = integers
def size(self):
return len(self.integers)
object_1 = Object([1, 4])
object_2 = Object([1, 3])
object_3 = Object([100])
def _find_subset_objects(integers): # type: (List[int]) -> List[Object]
raise NotImplementedError()
def test(find_subset_objects=_find_subset_objects):
assert find_subset_objects([1]) == []
assert find_subset_objects([1, 4]) == [object_1]
assert find_subset_objects([1, 3, 4]) == [object_1, object_2]
Is there some algorithm or some data struct is aim to solve this kind of problem?
Store the objects in an array. The indices will be 0 ... ~100K. Then create two helper arrays.
First one with the element counts for every object. I will call this array obj_total(This could be ommited by calling the object.size or something similar if you wish.)
Second one initialized with zeroes. I will call it current_object_count.
For every integer property p where 0 < p <= 20000, create a list of indices where index i in the list means that the element is contained in the i-th object.
It is getting messy and I'm getting lost in the names. Time for the example with the objects that you used in the question:
objects = [[1, 4], [1, 3], [100]]
obj_total = [2, 2, 1]
current_object_count = [0, 0, 0]
object_1_ref = [0, 1]
object_2_ref = [ ]
object_3_ref = [1]
object_4_ref = [0]
object_100_ref = [100]
object_refs = [object_1_ref ,object_2_ref , ... , object_100_ref]
#Note that you will want to do this references dynamically.
#I'm writing them out only for the sake of clarity.
Now we are given the input array, for example [1, 3, 4]. For every element i in the array, we look we look at the object_i_ref. We then use the indices in the reference array to increase the values in the current_object_count array.
Whenever you increase a value in the current_object_count[x], you also check against the obj_total[x] array. If the values match, the object in objects[x] is a subset of the input array and we can note it down.
When you finish with the input array you have all the results.
why the below given [] for a reverse order range in ruby
(0..5).to_a
# => [0, 1, 2, 3, 4, 5]
(5..0).to_a
# => []
I am new on ruby PL
what is the best way to use a reverse range in ruby
The best way to use a reverse range for iteration
I know .reverse of array
But can I inherit the range and make a custom method of it and use it as a range
I also try
class Range
def r
to_a.reverse
end
end
# => :r
(5..0).r
# => []
You asked why (5..0).to_a doesn't give the "expected result", by which I assume you mean [5,4,3,2,1].
If a range is a..b that means it includes all values x such that a <= x <= b.1 If a > b, no values are included, so nil is returned. There is no such thing as an "empty" range, as there is an empty array ([]), hash ({}), string ("") and so on. (1..1 is a range, but it is not empty.) That's why 5..3 cannot return a Range object, and therefore returns nil.
Ruby does not support the concept of a "reversed range". If you just want to step down from 3 to 1 there are many ways to do that without involving a range.
Note also that ranges, unlike arrays, for example, may contain an infinite number of values. 1.0..3.0 is one such example.
1 The range a...b (three dots) includes all values x such that a <= x < b.
what should I do if I need a reverse range
(0..5).to_a.reverse
#=> [5, 4, 3, 2, 1, 0]
or
(0..5).reverse_each.to_a
#=> [5, 4, 3, 2, 1, 0]
Here's a way to do it that might more closely express they way you're thinking about it:
(5.downto 0).to_a
=> [5, 4, 3, 2, 1, 0]
Try:
[*0..5].reverse
#=> [5, 4, 3, 2, 1, 0]
OR
> r = Proc.new {|x| x.reverse}
> r.call((0..5).to_a)
#=> [5, 4, 3, 2, 1, 0]
Let's say I have an Array that contains more than three repetitions of a given digit.
I want to remove only three of those repetitions, and leave any remaining instances of the digit in the resulting array.
For example:
a = [2, 2, 2, 1, 6]
b = a.map{|i|
num = a.select{|v| v == i}.size
num == 3 ? "" : i
}.reject{|v|
v == ""
}
gives me my desired result:
b == [1, 6]
However, in the below example, I want the last "2" to remain in the array.
# I want to reject ONLY triplets.
# In the below example, the last "2" should remain
a = [2, 2, 2, 1, 2]
b = a.map{|i|
num = a.select{|v| v == i}.size
num == 3 ? "" : i
}.reject{|v|
v == ""
}
The result here is:
b == [2, 2, 2, 1, 2]
I'd like the result to be:
b == [1, 2]
I also have another code block, similar to the one above, using a bit different logic, but ends up with the same result:
a = [2, 2, 2, 1, 2]
newdice = a.reject { |v|
if a.count(v) == 3
x = v
end
v == x
}
I'm at a loss, other than some nasty trickery that involves finding the index of the first instance of the 3x repeated digit, and slicing out [index, 2] from it. There's got to be a more "ruby-like" way.
Thanks!
This would remove the first 3 elements that are = 2
3.times{a.index(2)? a.delete_at(a.index(2)) : nil }
if you want to remove the first 3 of any digits in the array then something like:
(0..9).each{|n| 3.times{a.index(n)? a.delete_at(a.index(n)) : nil }}
Matt's version further modified using the if-modifier:
(0..9).each{|n| {3.times{a.delete_at(a.index(n))} if a.count(n) >= 3}
Not sure how you want item to be displayed but below are the easy options if you want use
a = [2, 2, 2, 1, 2]
a.last(2) => [1,2]
a.uniq => [1,2]
I'm trying to find a neat way of summing a list and a list of lists in the same function, so far I've got:
import operator
"""
Fails late for item = ['a', 'b']
"""
def validate(item):
try:
return sum(item) == sum(range(1, 10))
except TypeError:
return sum(reduce(operator.add, item)) == sum(range(1, 10))
"""
Not valid for item = [1,2,[3,4,5]]
"""
def validate2(item):
if isinstance(item[0], int):
return sum(item) == sum(range(1, 10))
else:
return sum(reduce(operator.add, item)) == sum(range(1, 10))
print validate([1, 2, 3, 4, 5, 6, 7, 8, 9])
print validate([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print validate2([1, 2, 3, 4, 5, 6, 7, 8, 9])
print validate2([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
...but neither of these seem quite right to me (reasons in the doc strings). What I want to know is if there is a better way of summing lists and lists of lists that doesn't require me to catch exceptions or actually analyse the list before the function decides what to do.
Obviously, I'm still expecting ['a', 'b'] to be invalid.
Perhaps you'd find it easier to flatten the list first?
def flatten(xs):
for x in xs:
try:
sub = iter(x)
except TypeError:
yield x
else:
for y in flatten(sub):
yield y
With the above, you can do this:
In [4]: fs = flatten([1,2,[3,4,[5,6],7],8,[9,10]])
In [5]: list(fs)
Out[5]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Don't forget to describe exactly what you're trying to do. I'm assuming you mean to sum all values to a single value, and not to get eg. [[1,2],[3,4]] -> [3,7]. Here's simple recursion; five lines of code if you skip the tests:
def sums(it):
"""
>>> sums(1)
1
>>> sums([1,2,3])
6
>>> sums([1,2,3,[4,5]])
15
>>> sums(['a','b'])
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'int' and 'str'
"""
if getattr(it, "__iter__", None):
return sum(map(sums, it))
else:
return it
if __name__ == "__main__":
import doctest
doctest.testmod()
The external numpy module has many operations (including sum()) which work similarly on scalars, vectors, matrices and even higher-dimensional arrays...
Note however that it doesn't work on mixed lists like [1,2,[3,4,5]], only square matrices! So it doesn't exactly answer your question.