Merge Two Sorted Arrays in Python - arrays

I have two sorted arrays
array1 = [0, 3, 4, 31]
array2 = [4, 6, 30]
I try to sort these arrays by using the code below:
def mergeSortedArray(array1, array2):
if not len(array1):
return array2
if not len(array2):
return array1
mergedArray = []
array1Item = array1[0]
array2Item = array2[0]
i = 0
j = 0
while (i < len(array1)) and (j < len(array2)):
if array1Item < array2Item:
mergedArray.append(array1Item)
array1Item = array1[i + 1]
i += 1
else:
mergedArray.append(array2Item)
print(j)
array2Item = array2[j + 1]
j += 1
return mergedArray
print(mergeSortedArray([0, 3, 4, 31], [4, 6, 30]))
But the terminal keep telling me that:
line 26, in mergeSortedArray
array2Item = array2[j + 1]
IndexError: list index out of range
I wonder which part I did wrong! Can someone explain to me? plz~
BTW, what is the syntactically cleanest way to accomplish this?

Make use of Python's features, such as merging two lists with the + operator. Then, simply sort the new list.
>>> array1 = [0, 3, 4, 31]
>>> array2 = [4, 6, 30]
>>> merged_array = array1 + array2
>>> merged_array.sort()
>>> merged_array
[0, 3, 4, 4, 6, 30, 31]

Related

Inner String array swap

I try to swap inner string array value with none additional array, stack...etc.
Example:
s = [1,2,3,4,5,6,7,8]
output= [1,5,2,6,3,7,4,8]
My solution shows as below, but I think isn't the best solution. Can someone correct my code efficiency?
[python3]
class Solution:
def inner_number(self, s):
i=len(s)//2
index=1
while i < len(s):
for j in range(i,index,-1):
s[j-1],s[j]=s[j],s[j-1]
i+=1
index+=2
return s
s = [1,2,3,4,5,6,7,8,9]
h = len(s)//2
res= []
if len(s)%2==1:
res = [j for i in zip(s[:h],s[h:]) for j in i] + [s[-1]]
else:
res = [j for i in zip(s[:h],s[h:]) for j in i]
print(res)
# output [1, 5, 2, 6, 3, 7, 4, 8, 9]
def inner_swap(input):
req_length = int(len(input)/2) if len(input) % 2 == 0 else int(len(input)/2)+1
s1 = input[:req_length]
s2 = input[req_length:]
result = [None]*len(input)
result[::2] = s1
result[1::2] = s2
return result
assert inner_swap([1, 2, 3, 4]) == [1, 3, 2, 4]
assert inner_swap([1, 2, 3, 4, 5]) == [1, 4, 2, 5, 3]

Merge two ordered arrays into one ordered array

I am writing a method that takes two sorted arrays and I want it to return a merged array with all the values sorted. Given the two arrays below:
array_one = [3, 4, 8]
array_two = [1, 5, 7]
I want my merge_arrays method to return:
[1, 3, 4, 5, 7, 8]
My current algorithm is below:
def merge_arrays(array_one, array_two)
merged_array_size = array_one.length + array_two.length
merged_array = []
current_index_on_one = 0
current_index_on_two = 0
current_merged_index = 0
for i in (0..merged_array_size - 1)
if array_one[current_index_on_one] < array_two[current_index_on_two]
merged_array[current_merged_index] = array_one[current_index_on_one]
current_index_on_one += 1
current_merged_index += 1
else
merged_array[current_merged_index] = array_two[current_index_on_two]
current_index_on_two += 1
current_merged_index += 1
end
end
return merged_array
end
I am getting an error 'undefined method `<' for nil:NilClass'. I don't understand how the conditional is receiving this. I debugged the variables in the conditionals and they are giving true or false values. I'm not sure what is causing this error.
Maybe I am missing the point but you can do:
(array_one + array_two).sort
=> [1, 3, 4, 5, 7, 8]
I am getting an error 'undefined method `<' for nil:NilClass'. I don't understand how the conditional is receiving this.
You start by comparing index 0 to index 0:
[3, 4, 8] [1, 5, 7]
0-----------0 #=> 3 < 1
Then you increment the lower value's index by 1:
[3, 4, 8] [1, 5, 7]
0--------------1 #=> 3 < 5
And so on:
[3, 4, 8] [1, 5, 7]
1-----------1 #=> 4 < 5
[3, 4, 8] [1, 5, 7]
2--------1 #=> 8 < 5
[3, 4, 8] [1, 5, 7]
2-----------2 #=> 8 < 7
At that point you get:
[3, 4, 8] [1, 5, 7]
2--------------3 #=> 8 < nil
Index 3 is outside the array's bounds, so array_two[current_index_on_two] returns nil and:
if array_one[current_index_on_one] < array_two[current_index_on_two]
# ...
end
becomes
if 8 < nil
# ...
end
resulting in ArgumentError(comparison of Integer with nil failed). If nil is on the left hand side, you'd get NoMethodError (undefined method `<' for nil:NilClass).
Here's one way you can write merge using recursion. Note, as you specified, both inputs must already be sorted otherwise the output will be invalid. The inputs can vary in size.
def merge (xs, ys)
if xs.empty?
ys
elsif ys.empty?
xs
else
x, *_xs = xs
y, *_ys = ys
if x < y
[x] + (merge _xs, ys)
else
[y] + (merge xs, _ys)
end
end
end
merge [ 1, 3, 4, 6, 8, 9 ], [ 0, 2, 5, 7 ]
# => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Assuming you have two sorted arrays. You need to create pipeline using recursion going to crunch through each array. checking at each iteration to see
which value at index 0 of either array is lower, removing that from the array and appending that value to the result array.
def merge_arrays(a, b)
# build a holder array that is the size of both input arrays O(n) space
result = []
# get lower head value
if a[0] < b[0]
result << a.shift
else
result << b.shift
end
# check to see if either array is empty
if a.length == 0
return result + b
elsif b.length == 0
return result + a
else
return result + merge_arrays(a, b)
end
end
> a = [3, 4, 6, 10, 11, 15]
> b = [1, 5, 8, 12, 14, 19]
> merge_arrays(a, b)
#=> [1, 3, 4, 5, 6, 8, 10, 11, 12, 14, 15, 19]
I made slight changes to your code in order to make it work. See the comments inside.
array_one = [2, 3, 4, 8, 10, 11, 12, 13, 15]
array_two = [1, 5, 6, 7, 9, 14]
def merge_arrays(array_one, array_two)
array_one, array_two = array_two, array_one if array_one.length > array_two.length # (1) swap arrays to make satement (3) work, need array_two always be the longest
merged_array_size = array_one.length + array_two.length
merged_array = []
current_index_on_one = 0
current_index_on_two = 0
current_merged_index = 0
for i in (0...merged_array_size-1) # (2) three points to avoid the error
if (!array_one[current_index_on_one].nil? && array_one[current_index_on_one] < array_two[current_index_on_two]) # (3) check also if array_one is nil
merged_array[current_merged_index] = array_one[current_index_on_one]
current_index_on_one += 1
current_merged_index += 1
else
merged_array[current_merged_index] = array_two[current_index_on_two]
current_index_on_two += 1
current_merged_index += 1
end
end
merged_array[current_merged_index] = array_one[current_index_on_one] || array_two[current_index_on_two] # (4) add the missing element at the end of the loop, looks what happen if you comment out this line
return merged_array
end
p merge_arrays(array_one, array_two)
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
The error was coming because the loop was making one step over. The solution is to stop before and insert the missing element at the end of the loop.
It works also with:
# for i in (1...merged_array_size)
# and
# for i in (1..merged_array_size-1)
# and
# (merged_array_size-1).times do
arr1 = [3, 4, 8, 9, 12]
arr2 = [1, 5, 7, 8, 13]
arr = [arr1, arr2]
idx = [0, 0]
(arr1.size + arr2.size).times.with_object([]) do |_,a|
imin = [0, 1].min_by { |i| arr[i][idx[i]] || Float::INFINITY }
a << arr[imin][idx[imin]]
idx[imin] += 1
end
#=> [1, 3, 4, 5, 7, 8, 8, 9, 12, 13]

Ruby - How do you perform an operation on each item of two (maybe more) arrays and populate them in a new array?

a = [6, 7, 8, 9, 10]
b = [1, 2, 3, 4, 5]
each of array a's items are divided by each of array b's items and put into a new array called c.
c = [6, 3, 2, 2, 2]
a = [6, 7, 8, 9, 10]
b = [1, 2, 3, 4, 5]
c = a.zip(b).map { |e| e.reduce :/ }
#⇒ [
# [0] 6,
# [1] 3,
# [2] 2,
# [3] 2,
# [4] 2
# ]
Array#zip zips the arrays together and then each element (array of 2 items zipped) is reduced with Integer#/.
I like mudasobwa's zip/map solution, but here are a couple alternatives:
a = [6, 7, 8, 9, 10]
b = [1, 2, 3, 4, 5]
c = Array.new(a.size) { |i| a[i] / b[i] }
c = a.map.with_index { |x, i| x / b[i] }
In particular, I might prefer the Array.new solution if the arrays aren't guaranteed to be the same length, because you can easily ensure you don't go over bounds:
c = Array.new([a.size, b.size].min) { |i| a[i] / b[i] }

Circular array slicing

I have an array with a varying number of elements 0..n elements. An example could be:
a = [0,1,2,3,4,5,6,7,8,9]
In an iterative process, I would like to move a cursor in the array and slice out a max number of elements. If I reach the "end" of the array, it should start over and pick from the beginning again:
Something like this:
4.times do |i|
a.slice(i * 3, 3)
end
# i = 0 => [0,1,2]
# i = 1 => [3,4,5]
# i = 2 => [6,7,8]
# i = 3 => [9,0,1]
# ...
However the last output i = 3 produces [9] as .slice does not do exactly what I want.
You could use cycle:
a.cycle.each_slice(3).take(4)
#=> [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]]
You could use Array#rotate, and then take the first 3 elements each time:
4.times.each { |i| a.rotate(i*3)[0..2] }
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 0, 1]]
Possible solution:
4.times { |i| p a.values_at(*(i*3..i*3+2).map {|e| e % 10 }) }
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
[9, 0, 1]
9%10 = 9, 10%10 = 0, 11%10 = 1. So you will get the desired output.
This might break some code, so be careful.
class Array
alias_method :old_slice, :slice
def slice(o, c)
ret = old_slice(o % size, c)
if ret.size != c
ret += old_slice(0, c - ret.size)
end
ret
end
end
a = [0,1,2,3,4,5,6,7,8,9]
4.times do |i|
p a.slice(i * 3, 3)
end
As Stephan points out it would be better to give this method a different name, or it might be even better to create a CircularArray class.
class CircularArray < Array
alias_method :straight_slice, :slice
def slice(o, c)
ret = straight_slice(o % size, c)
if ret.size != c
ret += straight_slice(0, c - ret.size)
end
ret
end
end

Sum the elements of two equal count arrays [duplicate]

Is there a concise way in Swift of creating an array by applying a binary operation on the elements of two other arrays?
For example:
let a = [1, 2, 3]
let b = [4, 5, 6]
let c = (0..<3).map{a[$0]+b[$0]} // c = [5, 7, 9]
If you use zip to combine the elements, you can refer to + with just +:
let a = [1, 2, 3]
let b = [4, 5, 6]
let c = zip(a, b).map(+) // [5, 7, 9]
Update:
You can use indices like this:
for index in a.indices{
sum.append(a[index] + b[index])
}
print(sum)// [5, 7, 9]
(Thanks to Alexander's comment this is better, because we don't have to deal with the element itself and we just deal with the index)
Old answer:
you can enumerate to get the index:
var sum = [Int]()
for (index, _) in a.enumerated(){
sum.append(a[index] + b[index])
}
print(sum)// [5, 7, 9]

Resources