Reputation: 661
I am trying to sort an array, but it always returns the same original input. Do you know why?
puts "Please tell me the array(separated by space, finish by enter twice):"
x = []
input = ' '
while input != ''
input = gets.chomp
x.push input
end
puts x.sort
Upvotes: 2
Views: 594
Reputation: 114188
Your code expects the items to be entered on separate lines. An easy "fix" is to adjust the help message:
puts "Please tell me the array (one item per line, finish by enter twice)"
And to provide the items as expected:
$ ruby sort.rb
Please tell me the array (one item per line, finish by enter twice)
b
c
a
a
b
c
Note that your code adds the empty line to the array. This can be fixed by checking input
:
x = []
input = ' '
while input != ''
input = gets.chomp
x.push input unless input.empty?
end
Having to check for an empty input
twice (input != ''
/ input.empty?
) and the random initial value (input = ' '
) can be avoided by using loop
and break
instead of while
:
x = []
loop do
input = gets.chomp
break if input.empty?
x.push input
end
Upvotes: 1
Reputation: 2820
If you are expecting to sort an array of numbers, change this line:
x.push input.to_i
Otherwise an input like:
4
10
1
Will be ordered:
1
10
4
If you are expecting strings, your program should work and more details should be provided.
Upvotes: 0
Reputation: 160551
Meditate on this:
x = [] # => []
input = '1 2 3' # => "1 2 3"
x.push input # => ["1 2 3"]
x.sort # => ["1 2 3"]
Basically, you're entering a single string in your code, pushing it into the array, then sorting a single element array. That's not going to do anything since you can't sort a single element array and get a different order. (Well, you can expect it to be different, but it won't be.)
Instead:
x = [] # => []
x.push '1' # => ["1"]
x.push '3' # => ["1", "3"]
x.push '2' # => ["1", "3", "2"]
That simulates entering three different strings. Sorting x
now returns a sorted array:
x.sort # => ["1", "2", "3"]
Here's something else to meditate on:
require 'fruity'
string = ('a'..'z').to_a.join(' ')
string # => "a b c d e f g h i j k l m n o p q r s t u v w x y z"
3.times do
compare do
split1 { string.split }
split2 { string.split(' ') }
split3 { string.split(/\s/) }
split4 { string.split(/\s+/) }
end
end
# >> Running each test 1024 times. Test will take about 1 second.
# >> split1 is faster than split2 by 10.000000000000009% ± 10.0%
# >> split2 is faster than split3 by 3x ± 0.1
# >> split3 is similar to split4
# >> Running each test 2048 times. Test will take about 1 second.
# >> split1 is faster than split2 by 10.000000000000009% ± 10.0%
# >> split2 is faster than split3 by 3x ± 0.1
# >> split3 is similar to split4
# >> Running each test 1024 times. Test will take about 1 second.
# >> split1 is faster than split2 by 10.000000000000009% ± 10.0%
# >> split2 is faster than split3 by 3x ± 0.1
# >> split3 is similar to split4
The results for split1
and split2
are about 10% in favor of split1
so sometimes Fruity reports a 10% difference and sometimes it doesn't. The same is true for split3
and split4
.
And:
string = ('a'..'z').to_a.zip(26.times.map{ ' ' * (rand(4) + 1)}).join
string # => "a b c d e f g h i j k l m n o p q r s t u v w x y z "
compare do
split1 { string.split }
split2 { string.split(' ') }
split3 { string.split(/\s/) }
split4 { string.split(/\s+/) }
end
# >> Running each test 1024 times. Test will take about 1 second.
# >> split1 is similar to split2
# >> split2 is faster than split4 by 3x ± 0.1
# >> split4 is faster than split3 by 2.1x ± 0.1 (results differ: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] vs ["a", "", "", "", "b", "", "c", "", "", "", "d", "", "", "", "e", "", "f", "", "", "g", "", "h", "", "", "i", "j", "", "k", "l", "", "m", "", "", "", "n", "", "o", "", "p", "q", "r", "", "", "", "s", "", "", "t", "", "", "u", "", "v", "w", "", "x", "", "", "", "y", "z"])
The last result is different because split(/\s/)
is only looking for single whitespace characters, not multiples like split(/\s+/)
does. I left that result in to show the different the +
can make to the engine.
Upvotes: 2
Reputation: 52357
Use String#split
. Take a look:
x = '1 3 2 4 55'
x.split.sort
#=> ["1", "2", "3", "4", "55"]
If x
is an array of strings, you can do the following:
x = ['1 3 100', '2 30 4 10']
x.flat_map { |string| string.split }.sort
#=> ["1", "10", "100", "2", "3", "30", "4"] Note it is sorted alphabetically.
If you want to sort input numerically consider this:
x = ['1 3 100', '2 30 4 10']
x.flat_map { |string| string.split.map(&:to_i) }.sort
#=> [1, 2, 3, 4, 10, 30, 100]
Though in real life I would prefer @tadman's solution, because it operates on the input immediately, unifying it.
Upvotes: 3
Reputation: 211610
You need to both split
the input and concat
to a singular array:
x = [ ]
loop do
input = gets.chomp
break if (input.empty?)
x += input.split
end
puts x.sort
Upvotes: 6
Reputation: 19879
If you're entering all the numbers on a single line then you only need one call to gets
. See the below. We read a single line of input, split the input on any number of spaces and convert the values to their integer form. Then we display them sorted.
$ cat foo.rb
puts "Please tell me the array(separated by space, finish by enter twice):"
input = gets.chomp
x = input.split(/\s+/).map(&:to_i)
puts x.sort
$ ruby foo.rb
Please tell me the array(separated by space, finish by enter twice):
2423 888 3333 222
222
888
2423
3333
Upvotes: 1