I have to write a function that inserts multiple elements into a single dimension array of unknown length.
For example:
input_array = [1, 2, 3, 4, 5]
Inserting two zeroes between each element, to give:
output_array = [1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5]
.....
Any ideas?
Here is two versions of the code.
Simple for loop:
input_array = [1, 2, 3, 4, 5]
output_array = []
for k in input_array:
output_array.append(k)
output_array.append(0)
output_array.append(0)
print(output_array)
Using list comprehensions:
input_array = [1, 2, 3, 4, 5]
output_array = [item for sublist in [[x, 0, 0] for x in input_array] for item in sublist])
print(output_array)
I can't say whether the asker, as #Willem notes, was looking for a faster solution than he/she himself/herself was able to come up with. In reality, this seems like a simple task:
def fill(iterable, padding: tuple):
result = list()
for i in iterable:
# The * symbol is a sequence unpacking and it serves to flatten the values inside result
# For example, [*(0, 1, 2)] equals [0, 1, 2] and not [(0, 1, 2)]
result.extend([i, *padding])
return result
if __name__ == "__main__":
data = range(1, 6)
padding = (0, 0)
print(fill(data, padding))
I could obviously choose any other container type in place of list assigned to result.
Below is what the above script outputs when running on my machine:
None#vacuum:~$ python3.6 ./test.py
[1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0, 5, 0, 0]
Related
Suppose there's a numpy 2D array as follows:
>>> x = np.array([[4,2,3,1,1], [1,0,3,2,1], [1,4,4,3,4]])
>>> x
array([[4, 2, 3, 1, 1],
[1, 0, 3, 2, 1],
[1, 4, 4, 3, 4]])
My objective is to - find the first occurrence of value 4 in each row, and set the rest of the elements (including that element) in that row to 0. Hence, after this operation, the transformed array should look like:
>>> x_new
array([[0, 0, 0, 0, 0],
[1, 0, 3, 2, 1],
[1, 0, 0, 0, 0]])
What is the pythonic and optimized way of doing this? I tried with a combination of np.argmax() and np.take() but was unable to achieve the end objective.
You can do it using a cumulative sum across the columns (i.e. axis=1) and boolean indexing:
n = 4
idx = np.cumsum(x == n, axis=1) > 0
x[idx] = 0
or maybe a better way is to do a cumulative (logical) or:
idx = np.logical_or.accumulate(x == n, axis=1)
I am trying to find the common elements in two arrays.
pairs = Array.new
a = exchange_one.get_symbols
b = exchange_two.get_symbols
c = a+b
c.uniq{|pair| pairs << pair}
I am combining the two arrays using +
Then I am calling uniq to remove the duplicate, but passing it to a block so the found duplicates can be added to an array before they are deleted.
For some reason the array pairs is just the entire c array.
What is the correct way to find array similarities.
If your goal is simply to determine which elements are the same between two arrays, you can use the intersection operator Array#&.
a = exchange_one.get_symbols
b = exchange_two.get_symbols
intersection = a & b
First understand what are you doing and what you want.
For eg.
a = 15.times.map { rand 6 }
#=> [1, 0, 5, 3, 1, 3, 4, 1, 3, 2, 1, 2, 4, 2, 3]
b = 15.times.map { rand 6 }
#=> [3, 3, 3, 1, 3, 1, 3, 1, 5, 1, 4, 2, 0, 0, 4]
Now what are you doing
c = a + b
#=> [1, 0, 5, 3, 1, 3, 4, 1, 3, 2, 1, 2, 4, 2, 3, 3, 3, 3, 1, 3, 1, 3, 1, 5, 1, 4, 2, 0, 0, 4]
c - only combine arrays irrespective of content hence get all values.
Now
pairs = Array.new
c.uniq{|pair| pairs << pair}
Here uniq is just act as a iterator means if you check 'pair' then it iterate all the values of 'c' and insert those values in 'pairs' array.
check this
c.uniq{|pair| puts pair}
Thats why you are getting all values within 'pairs' array.
The best way to find similarity in arrays is (a&b), but you can make changes in your code as follow to achieve it.
pairs = (arr1+arr2).uniq
OR
pairs = arr1 & arr2 #best and efficient way.
Suppose:
arr1 = 15.times.map { rand 6 }
#=> [1, 0, 4, 0, 2, 3, 1, 0, 2, 4, 4, 1, 3, 1, 1]
arr2 = 15.times.map { rand 6 }
#=> [5, 5, 4, 1, 5, 1, 5, 0, 4, 0, 2, 0, 4, 5, 0]
arr1 contains 5 1s and arr2 contains 2 1s. If, by "common elements" you wish to report that both arrays contain [5, 2].min #=> 2 1s, and similar counts for the other elements that appear in either array, you can do the following:
h1 = count(arr1)
#=> {1=>5, 0=>3, 4=>3, 2=>2, 3=>2}
h2 = count(arr2)
#=> {5=>5, 4=>3, 1=>2, 0=>4, 2=>1}
(h1.keys | h2.keys).each_with_object({}) { |k,h| h[k] = [h1[k], h2[k]].min }
#=> {1=>2, 0=>3, 4=>3, 2=>1, 3=>0, 5=>0}
def count(arr)
arr.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
end
I have a problem with Array.count method on a two-dimensional array.
I load my two-dimensional array from have a file where I have stored before, something like this:
[[1, 1, 1, 1, 1, 2, 2, 1, 1, 1], [1, 1, 1, 1, 1, 2, 2, 1, 1, 1], [1, 1, 1, 1, 1, 2, 2, 1, 1, 1], [1, 1, 1, 1, 1, 2, 2, 1, 1, 1], [1, 1, 1, 1, 1, 2, 2, 1, 1, 1], [1, 1, 1, 1, 1, 2, 2, 1, 1, 1], [1, 4, 4, 5, 1, 2, 2, 1, 1, 1], [1, 4, 4, 5, 1, 2, 2, 1, 1, 1], [1, 4, 4, 1, 2, 2, 1, 1, 1, 1], [1, 4, 4, 1, 0, 0, 1, 1, 1, 1]]
I made this class called Maps:
require 'json'
class Maps
def initialize(filename)
#map = JSON.parse(File.read(filename))
end
def isCorrupted?
#map.count(0) > 1 ? true : false
end
end
and when I try to use my class method isCorrupted? the result it's always false.
require_relative 'classes/maps'
current_map = Maps.new("test.txt")
puts current_map.isCorrupted?
I don't understand why the method doesn't find the two 0 in the ten sub-array and return FALSE.
I also try to modify the method to get the count occurrences, like this:
#map.count(0)
but the result it's always 0.
Can someone help me? I need to know the total number of ZERO in the global array.
Edit-2: Flatten was what I need.
Using flatten does not work here.
Doing so would be a valid optimisation, if the requirement was simply to check whether any 0 is present in the nested arrays. But that's not what you're doing here; you want to check that more than one 0 appears in any array.
For example, you want to consider the following as non-corrupt, but poashin's answer would consider it as corrupt:
[[0, 1], [1, 0]]
Therefore, you should iterate through the arrays:
require 'json'
class Maps
def initialize(filename)
#map = JSON.parse(File.read(filename))
end
def is_corrupted?
#map.any? { |row| row.count(0) > 1 }
end
end
(Minor point: I have followed the ruby style guide conventions here, and used snake_case for the method name, not camelCase.)
Now your code doesn't work the way you intend it to cause you are trying to count 0 elements in the collection of arrays (not integers).
In case you need to know if there are more than two zeroes in all subarrays in total:
#map.flatten.count(0) > 1
In case you want to know if there are subarrays that include one or more zeroes you should use another approach:
#map.any? { |collection| collection.count(0) > 1 }
I have the following array:
arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
Without changing the order of the values, I need to subdivide arr into smaller arrays at every occurrence of 0, such that the result would be:
arr = [ [0, 1, 1, 2, 3, 1], [0], [0, 1] ]
If arr were a string, I could use .split("0") and then prepend the delimiter to each subarray. What would be the most efficient equivalent to .split() in plain Ruby for arrays?
Enumerable#slice_before does this exact thing:
arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
p arr.slice_before(0).to_a
# => [[0, 1, 1, 2, 3, 1], [0], [0, 1]]
See it on repl.it: https://repl.it/FBhg
Since ActiveSupport defines an Array#split method in Ruby, we can use it as a starting point:
class Array
def split(value = nil)
arr = dup
result = []
if block_given?
while (idx = arr.index { |i| yield i })
result << arr.shift(idx)
arr.shift
end
else
while (idx = arr.index(value))
result << arr.shift(idx)
arr.shift
end
end
result << arr
end
end
# then, using the above to achieve your goal:
arr = [0, 1, 1, 2, 3, 1, 0, 0, 1]
arr.split(0).map { |sub| sub.unshift(0) }
# => [[0], [0, 1, 1, 2, 3, 1], [0], [0, 1]]
Note that your verbal phrasing of the algorithm (split and prepend) is what is happening here, but your expected output is different (there's an additional zero because of the way split works).
Do you want to split before each zero? For this you could use slice_before.
Do you want to split but drop empty arrays? This could be done with a quick compact before prepending, but you would lose the [0] subarray.
Do you want to split but drop the first element if empty?
Do you want to split on /0+/?
I am having trouble dissecting this data. I would like to find out how many #1 are in each list. After finding that number, I would like to append it to another list for later.
I seem to be getting the input:
--> [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
When I really want:
--> [2, 2, 2, 2, 0, 2, 2, 1, 11, 0]
This is the code:
d = []
count = 0
b = [[1,3,6,2,7,3,9,2,7,1,7],
[1,5,8,3,0,3,6,2,7,2,1],
[1,5,2,6,8,6,2,5,1,8,9],
[5,2,5,2,1,8,1,5,2,4,6],
[5,7,2,7,3,7,3,7,3,9,2],
[1,5,8,3,0,3,6,2,7,2,1],
[5,2,5,2,1,8,1,5,2,4,6],
[3,6,1,5,7,8,4,3,6,3,3],
[1,1,1,1,1,1,1,1,1,1,1],
[3,4,5,6,8,5,7,5,7,3,7]]
for i in b:
for x in b:
if x == 1:
count =+ 1
d.append(count)
count = 0
print(d)
You are iterating over the wrong object in your second for loop, I believe you meant:
for x in i:
This is why you are getting 0s
There is a Counter class in the standard collections module, so you can simplify this:
>>> from collections import Counter
>>> [Counter(i)[1] for i in b]
[2, 2, 2, 2, 0, 2, 2, 1, 11, 0]
You can also do this without the Counter class a bit more verbosely:
>>> [sum(1 for x in i if x == 1) for i in b]
[2, 2, 2, 2, 0, 2, 2, 1, 11, 0]