how to Split and get data in ruby - ruby

I am newbie in ruby.
Now, I have problem about text splitting by ruby programming.
My text is like
AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700|DD:0.71:1700:2010|EE:1.00:2070:2390
So I need result to (process until end of text)
AA 0.88
BB 0.82
CC 0.77
DD 0.71
EE 1.00
How to coding it. Now I can only split by "|".
Best regard.

Use String#split:
s = 'AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700|DD:0.71:1700:2010|EE:1.00:2070:2390'
s.split('|').each do |substring|
name, num, * = substring.split(':')
puts "#{name} #{num}"
end
output:
AA 0.88
BB 0.82
CC 0.77
DD 0.71
EE 1.00

And here, just for reference, is a regexp version:
s = 'AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700|DD:0.71:1700:2010|EE:1.00:2070:2390'
p s.scan /(?:\||\A)([^:]+):([^:]+)/
# => [["AA", "0.88"], ["BB", "0.82"], ["CC", "0.77"], ["DD", "0.71"], ["EE", "1.00"]]
The code is shorter but much harder to read and debug. Use the other answers before this one!
Edit:
And here is the same regexp with some comments:
s.scan %r{
(?: \| | \A) # Look for start of string (\A) or '|' (\|) but do not include in capture (?:)
([^:]+) # Look for and capture one or more characters that are not ':'
: # Look for but do not capture a ':', Not captured as line is not in parenthesis.
([^:]+) # Repeat second line.
}x # x modifies the regexp to allow comments.

s = 'AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700'
s.split('|').map { |item| # produces an array and remaps it
s1, s2, * = item.split(':')
puts "#{s1} #{s2}"
[s1, s2]
}
Hope it helps.

Using gsub and
regex:
str = "AA:0.88:320:800|BB:0.82:1040:1330|CC:0.77:1330:1700|" +
"DD:0.71:1700:2010|EE:1.00:2070:2390"
puts str.gsub(':',' ').scan(/(([A-Z])\2 \d\.\d\d)/).map(&:first)
AA 0.88
BB 0.82
CC 0.77
DD 0.71
EE 1.00
These are the steps:
s1 = str.gsub(':',' ')
# => "AA 0.88 320 800|BB 0.82 1040 1330|CC 0.77 1330 1700|
DD 0.71 1700 2010|EE 1.00 2070 2390" (broken for display)
s2 = s1.scan(/(([A-Z])\2 \d\.\d\d)/)
# => [["AA 0.88", "A"], ["BB 0.82", "B"], ["CC 0.77", "C"],
["DD 0.71", "D"], ["EE 1.00", "E"]]
s3 = s2.map(&:first)
# => ["AA 0.88", "BB 0.82", "CC 0.77", "DD 0.71", "EE 1.00"]
In the regex, /(...)/ and ([A-Z]) are the first and second capture groups, respectively. \2 equals what is captured by the second group, so `([A-Z])\2 requires that the same two capital letters appear together (e.g., 'CC').

Related

How to print octal value or binary value in ruby programming language?

How do i just enter octal value or binary value to print in ruby as Integer
i tried that an it works but is there any other way?
puts '1011'.to_i(2) # => 11
A few ways. You can either prepend your number with radix indicators (where 0= octal or 0b = binary):
01011
#=> 521
0b1011
#=> 11
...or you can use Integer() to either prepend those radix indicators to a string...
number = '1011'
Integer("0#{number}")
#=> 521
Integer("0b#{number}")
#=> 11
...or to supply the desired base as a a second argument:
Integer('1011', 8)
#=> 521
Integer('1011', 2)
#=> 11
There's also the oct method for converting string to octal but I don't believe it has a binary counterpart:
'1011'.oct
#=> 521
try this
# Binary to Integer
# puts 0b(binary)
puts 0b1011 => 11
puts 0b1011.class => Integer
# Octal to Integer
# puts (octal_value)
puts 0366 => 246
puts 0b1011.class => Integer
# Hex to Integer
# puts 0x(hex value)
puts 0xff => 255
puts 0xff.class => Integer

How to format Phone string in Ruby with hyphens?

I have a problem I can't solve.
I need to write phone_format method that would accept any phone string and output it in groups of 3 digits with hyphens
phone_format("555 123 1234") => "555-123-12-34"
phone_format("(+1) 888 33x19") => "188-833-19"
But if it ends with single digit like 999-9, change it to 99-99. Ideally it would be a one liner
R = /
\d{2,3} # match 2 or 3 digits (greedily)
(?= # begin positive lookahead
\d{2,3} # match 2 or 3 digits
| # or
\z # match the end of the string
) # end positive lookahead
/x # free-spacing regex definition mode
Conventionally written
R = /\d{2,3}(?=\d{2,3}|\z)/
def doit(str)
s = str.gsub(/\D/,'')
return s if s.size < 4
s.scan(R).join('-')
end
doit "555 123 123"
#=> "555-123-123"
doit "555 123 1234"
#=> "555-123-12-34"
doit "555 123 12345"
#=> "555-123-123-45"
doit "(+1) 888 33x19"
#=> "188-833-19"
doit "123"
#=> "123"
doit "1234"
#=> "12-34"
Not really a one-liner: you need to handle the special cases.
def cut_by(str, cut)
str.each_char.each_slice(cut).map(&:join).join('-')
end
def phone_format(str)
str = str.gsub(/\D/, '') # cleanup
if str.size == 4 # special case 1
cut_by(str, 2)
elsif str.size % 3 == 1 # special case 2
cut_by(str[0..-5], 3) + "-" + cut_by(str[-4..], 2)
else # normal case
cut_by(str, 3)
end
end

ruby - tab from row not respected

I'm reading a simple txt file very well. However i'm getting the data row with tab not respected.
Below the row in the file.
Anderson Silva R$10 off R$20 of food 10.0 2 987 Fake St Batman Inc
And below is the out line at pry.
As we can see the 987 and Fake St is together in the same row.
Anderson Silva
R$10 off R$20 of food
10.0
2
987 Fake St
Batman Inc
and here the simple code
line.split("\t").map do |col|
col = col.split("\t")
puts col
end
I don't know if I'm understanding your question correctly, but I'd suspect that there's not actually a tab where you expect one.
def contrived_method(str)
str.split("\t").each do |col|
col = col.split("\t")
puts col
end
end
line1 = "10.0\t2\t987 Fake St"
line2 = "10.0\t2\t987\tFake St"
contrived_method(line1)
#=> 10.0
#=> 2
#=> 987 Fake St
contrived_method(line2)
#=> 10.0
#=> 2
#=> 987
#=> Fake St
For demonstration, I've reduced the size of your string to show that the String::split method will indeed split on the supplied delimiter. And--in this case--I've used eachinstead of mapbecause there's no assignment.
You'll find the inspect method valuable in this case:
line1 = "10.0\t2\t987 Fake St"
puts line1.inspect
#=> "10.0\t2\t987 Fake St"
puts line1
#=> 10.0 2 987 Fake St

How to separate the text file's values using the start and end positions

I have a text file:
GLKIIM 08052016 08052016 444-22222222 33333 5675555
ABCDEF 87645123 34211016 333-11111111 22222 5123455
I am using CSV.read to read the text file.
For each line in the text file, I need to extract the column values by the start and end positions. For that I have arrays:
start_pos = [1 8 17 26 30 39 45]
end_pos = [6 15 24 28 37 43 51]
which mean in the text file from position start_pos[0] to end_pos[0], i.e 1 to 6, we will have the first column's values, GLKIIM and ABCDEF.
The column names are:
column_name = [SOURCE_NAME BATCH_DATE EFFECT_DATE ID ACCOUNT_NO ENTITY ACCOUNT]
I need to create a hash as follows:
{
0=>{"SOURCE_NAME"=>"GLKIIM", "BATCH_DATE"=>"08052016", "EFFECT_DATE"=>"08052016", "ID"=>"444", "ACCOUNT_NO"=>"22222222", "ENTITY"=>"33333", "ACCOUNT"=>"5675555"},
1=>{"SOURCE_NAME"=>"ABCDEF", "BATCH_DATE"=>"87645123", "EFFECT_DATE"=>"34211016", "ID"=>"333", "ACCOUNT_NO"=>"11111111", "ENTITY"=>"22222", "ACCOUNT"=>"5123455"}
}
I cannot use space () as a delimiter to segregate the columns values, I need to use the start and end positions.
input = 'GLKIIM 08052016 08052016 444-22222222 33333 5675555
ABCDEF 87645123 34211016 333-11111111 22222 5123455'
start_pos = %w|1 8 17 26 30 39 45|.map &:to_i
end_pos = %w|6 15 24 28 37 43 51|.map &:to_i
input.split($/).map do |line|
start_pos.zip(end_pos).map { |s, e| line[s-1..e-1] }
end
#⇒  [["GLKIIM", "08052016", "08052016", "444", "22222222", "33333", "5675555"],
# ["ABCDEF", "87645123", "34211016", "333", "11111111", "22222", "5123455"]]
Do not read the file as a Comma-Separated-Values (CSV) file, if it isn't one.
Using "speaking code" you could use File.readlines instead:
#!/bin/env ruby
result = ARGF.readlines.map do |line|
[line[0..5], line[7..14], line[16..23], line[24..36]]
end
puts result.inspect
# => [["GLKIIM", "08052016", "08052016", " 444-22222222"], ["ABCDEF", "87645123", "34211016", " 333-11111111"]]
If you save this script you can run it as:
readliner.rb MYFILE.TXT MYFILE2.TXT MYFILE3.TXT
or pipe into it:
cat myfile | readliner.rb
Alternatively use
File.readlines("MYFILE.TXT")
instead of ARGF.readlines in the script.
The use of readlines can bring problems with it, as it reads the whole file into memory to yield an array of lines. See the comments for a small discussion on that topic.
Let's code-golf a bit, while staying somewhat readable and removing readlines:
#!/bin/env ruby
COLS = { "SOURCE_NAME" => 0..5,
"BATCH_DATE" => 7..14,
"EFFECT_DATE" => 16..23 }
result = ARGF.each_with_index.map do |line, idx|
[idx, COLS.map{|name,range| [name, line[range]] }.to_h ]
end.to_h
puts result.inspect
# => {0=>{"SOURCE_NAME"=>"GLKIIM", "BATCH_DATE"=>"08052016", "EFFECT_DATE"=>"08052016"}, 1=>{"SOURCE_NAME"=>"ABCDEF", "BATCH_DATE"=>"87645123", "EFFECT_DATE"=>"34211016"}}
I used below code:
file = File.open('abc.TXT', "r")
i = 0
file.each_line do |line|
temp = {}
for itrator in 0..column_name.length-1
temp[column_name[itrator]] = line[start_pos[itrator]-1..end_pos[itrator]-1]
end
data_hash[i] = temp
i+=1
end
puts data_hash
Assuming that file name containing the following data is abc.txt:
GLKIIM 08052016 08052016 444-22222222 33333 5675555
ABCDEF 87645123 34211016 333-11111111 22222 5123455

How to format string in Ruby using printf/sprintf

I want to create a table:
Iterations Value
1 123
2 124
..
100 124212
101 1242142
If I'm able to do so, do you know which website for reference is good for Ruby?
Already asked here:
Is there a Ruby equivalent to the C++ std::setw(int) function?
puts "%10s" % ["foo"] # => " foo"
puts "%-10s" % ["bar"] # => "foo "
You can use rjust or ljust.
"123".rjust(10, '0')
#=> "0000000123"
"123".ljust(10, '0')
#=> "1230000000"

Resources