ruby arrays can each_with_index do steps? - ruby

I have a txt file of records:
firstname lastname dob ssn status1 status2 status3 status4 firstname lastname dob ...
I can get this into an array:
tokens[0] = firstname
...
tokens[8] = firstname (of record 2).
tokens[9] = lastname (of record 2) and so on.
I want to iterate over tokens array in steps so I can say:
record1 = tokens[index] + tokens[index+1] + tokens[index+2] etc.
and the step (in the above example 8) would handle the records:
record2, record3 etc etc.
step 0 index is 0
step 1 (step set to 8 so index is 8)
etc.
I guess I should say these records are coming from a txt file that I called .split on:
file = File.open(ARGV[0], 'r')
line = ""
while !file.eof?
line = file.readline
end
##knowing a set is how many fields, do it over and over again.
tokens = line.split(" ")

Does this help?
tokens = (1..80).to_a #just an array
tokens.each_slice(8).with_index {|slice, index|p index; p slice}
#0
#[1, 2, 3, 4, 5, 6, 7, 8]
#1
#[9, 10, 11, 12, 13, 14, 15, 16]
#...

Using each_slice you could also assign variables to your fields inside the block:
tokens.each_slice(8) { |firstname, lastname, dob, ssn, status1, status2, status3, status4|
puts "firstname: #{firstname}"
}

Related

order records based on a field value on the order of an array of ids in rails

As part of sorting based on priority_id column label names, I have done the below code:
products = Product.where(id: pr_ids).order("priority_id IN(?)",ordered_priority_ids)
The below error is showing:
ActiveRecord::StatementInvalid (PG::SyntaxError: ERROR: syntax error at or near ")"
LINE 1: ...ducts"."id" IN ($2, $3) ORDER BY priority_id IN(?), 4, 2, 3...
^
):
Please help.
Thanks
def self.order_by_priority_ids(ids)
return self.where(:id => 0) if ids.blank?
values = []
ids.each_with_index do |priority_id, index|
values << "(#{priority_id}, #{index + 1})"
end
return self.joins("JOIN (VALUES #{values.join(",")}) as x (priority_id, ordering) ON #{table_name}.priority_id = x.priority_id").reorder('x.ordering')
end
And then you can use:
Product.where(id: pr_ids).order_by_priority_ids(ordered_priority_ids)

Problem with combobox, it didn't load de options (pyqt5)

I have a program that when I press a pushbutton it loads the options of my combombox, I have three, but for a unknown reason only two works. This function read a .txt file, and then put the strings in the combobox. I tried with addItem() and addItems(), made function again and it didn't work. The function read another two combobox and then loads the options.This is the function:
def cargar_combobox_flujos2(self,event):
anho = int(self.ui.combobox_anho.itemText(self.ui.combobox_anho.currentIndex()))
mes_input = self.ui.combobox_mes.itemText(self.ui.combobox_mes.currentIndex())
dic = {'Enero': 1, 'Febrero': 2, 'Marzo': 3, 'Abril': 4, 'Junio': 5, 'Julio': 7, 'Agosto': 8, 'Septiembre': 9,
'Octubre': 10, 'Noviembre': 11, 'Diciembre': 12}
mes = int(dic.get(mes_input))
lista_ssee=[]
nombre_txt='Graficos Flujos/lista_cbbx_'+str(anho)+'_'+str(mes)+'.txt'
if os.path.isfile(nombre_txt)==True:
archivo = open(nombre_txt, 'r')
c=archivo.read()
lista=c.split(',')
for i in lista:
lista_ssee.append(i)
archivo.close()
option_barras= self.ui.comboBox_barras_CMg2.count()
if option_barras > 1:
self.ui.comboBox_barras_CMg2.clear()
for barra in lista_ssee:
self.ui.comboBox_barras_CMg2.addItems(barra)

Algorith to remove duplicate records and records with a repetitive pattern

I have some records in a database tracking the price development on some items. These records often contains duplicates and repetitive sequences of price changes. I need to clean those up. Consider the following:
Record = Struct.new(:id, :created_at, :price)
records = [
Record.new(1, Date.parse('2017-01-01'), 150_000),
Record.new(2, Date.parse('2017-01-02'), 150_000),
Record.new(3, Date.parse('2017-01-03'), 130_000),
Record.new(4, Date.parse('2017-01-04'), 140_000),
Record.new(5, Date.parse('2017-01-05'), 140_000),
Record.new(6, Date.parse('2017-01-06'), 137_000),
Record.new(7, Date.parse('2017-01-07'), 140_000),
Record.new(8, Date.parse('2017-01-08'), 140_000),
Record.new(9, Date.parse('2017-01-09'), 137_000),
Record.new(10, Date.parse('2017-01-10'), 140_000),
Record.new(11, Date.parse('2017-01-11'), 137_000),
Record.new(12, Date.parse('2017-01-12'), 140_000),
Record.new(13, Date.parse('2017-01-13'), 132_000),
Record.new(14, Date.parse('2017-01-14'), 130_000),
Record.new(14, Date.parse('2017-01-15'), 132_000)
]
The policy should in plain words should be:
Remove any duplicates of exactly the same price immediately following each other.
Remove any records of a sequence of records with the same two prices jumping up and down for 2 times or more (e.g. [120, 110, 120, 110] but not [120, 110, 120]), so that only the initial price change is preserved.
In the above example the output that I would expect should be:
[
Record#<id: 1, created_at: Date#<'2017-01-01'>, price: 150_000>,
Record#<id: 3, created_at: Date#<'2017-01-03'>, price: 130_000>,
Record#<id: 4, created_at: Date#<'2017-01-04'>, price: 140_000>,
Record#<id: 6, created_at: Date#<'2017-01-06'>, price: 137_000>,
Record#<id: 13, created_at: Date#<'2017-01-13'>, price: 132_000>,
Record#<id: 14, created_at: Date#<'2017-01-14'>, price: 130_000>,
Record#<id: 14, created_at: Date#<'2017-01-14'>, price: 132_000>
]
Note: This is the most complicated example I can think of for the time being, if I find more, I'll update the question.
I have no problem dear sir of helping you with your challenge, here you go:
records_to_delete = []
# Cleanup duplicates
records.each_with_index do |record, i|
if i != 0 && record.price == records[i - 1].price
records_to_delete << record.id
end
end
records = records.delete_if{|record| records_to_delete.include?(record.id)}
# Remove repetitions
records_to_delete = []
records.each_with_index do |record, i|
if record.price == records[i + 2]&.price && records[i + 1]&.price == records[i + 3]&.price
records_to_delete << records[i+2].id
records_to_delete << records[i+3].id
end
end
records = records.delete_if{|record| records_to_delete.uniq.include?(record.id)}

Parsing a string field

I have these Syslog messages:
N 4000000 PROD 15307 23:58:12.13 JOB78035 00000000 $HASP395 GGIVJS27 ENDED\r
NI0000000 PROD 15307 23:58:13.41 STC81508 00000200 $A J78036 /* CA-JOBTRAC JOB RELEASE */\r
I would like to parse these messages into various fields in a Hash, e.g.:
event['recordtype'] #=> "N"
event['routingcode'] #=> "4000000"
event['systemname'] #=> "PROD"
event['datetime'] #=> "15307 23:58:12.13"
event['jobid'] #=> "JOB78035"
event['flag'] #=> "00000000"
event['messageid'] #=> "$HASP395"
event['logmessage'] #=> "$HASP395 GGIVJS27 ENDED\r"
This is the code I have currently:
message = event["message"];
if message.to_s != "" then
if message[2] == " " then
array = message.split(%Q[ ]);
event[%q[recordtype]] = array[0];
event[%q[routingcode]] = array[1];
event[%q[systemname]] = array[2];
event[%q[datetime]] = array[3] + " " +array[4];
event[%q[jobid]] = message[38,8];
event[%q[flags]] = message[47,8];
event[%q[messageid]] = message[57,8];
event[%q[logmessage]] = message[56..-1];
else
array = message.split(%Q[ ]);
event[%q[recordtype]] = array[0][0,2];
event[%q[routingcode]] = array[0][2..-1];
event[%q[systemname]] = array[1];
event[%q[datetime]] = array[2] + " "+array[3];
event[%q[jobid]] = message[38,8];
event[%q[flags]] = message[47,8];
event[%q[messageid]] = message[57,8];
event[%q[logmessage]] = message[56..-1];
end
end
I'm looking to improve the above code. I think I could use a regular expression, but I don't know how to approach it.
You can't use split(' ') or a default split to process your fields because you are dealing with columnar data that has fields that have no whitespace between them, resulting in your array being off. Instead, you have to pick apart each record by columns.
There are many ways to do that but the simplest and probably fastest, is indexing into a string and grabbing n characters:
'foo'[0, 1] # => "f"
'foo'[1, 2] # => "oo"
The first means "starting at index 0 in the string, grab one character." The second means "starting at index 1 in the string, grab two characters."
Alternately, you could tell Ruby to extract by ranges:
'foo'[0 .. 0] # => "f"
'foo'[1 .. 2] # => "oo"
These are documented in the String class.
This makes writing code that's easily understood:
record_type = message[ 0 .. 1 ].rstrip
routing_code = message[ 2 .. 8 ]
system_name = message[ 10 .. 17 ]
Once you have your fields captured add them to a hash:
{
'recordtype' => record_type,
'routingcode' => routing_code,
'systemname' => system_name,
'datetime' => date_time,
'jobid' => job_id,
'flags' => flags,
'messageid' => message_id,
'logmessage' => log_message,
}
While you could use a regular expression there's not much gained using one, it's just another way of doing it. If you were picking data out of free-form text it'd be more useful, but in columnar data it tends to result in visual noise that makes maintenance more difficult. I'd recommend simply determining your columns then cutting the data you need based on those from each line.

Ruby code to extract data from irregular text with intelligence

I am trying to write a ruby code to extract data from specific location from irregular text content.
The following is the text content something I am looking at.
Address1 Address2
adress1, adress1, # 34 , adress1,
4th Floor, Plot # 14 & 15,
Drive,, HARIKA BHIMANI
Madhapur, Hyderabad - 500081 2-14-117/35-1 Nas
Andhra Pradesh AP
+(91)40-00000000
xyz#dabc.com
This is my weird text and I want to extract Address1 and Address2 separately.
I thought I will try split but did not get how to extract Address1 and Address2 separately since both of them are in the single line. The space between content of Address1 and Address2 will be more than 2 space for sure.
I am planning to parse each line and split string in each line with separator more than 1 space. How do split the string in ruby with separator character more than two space ?
We can ignore the first 2 lines in the above text and start from 3rd line. Basically I want to separate out left side and right side data. The separator is more than 2 spaces. I have edited the question with my sample coding but it is failing if one of the line in the left side data is empty
I have tried following sample
if !line.empty?
splits = line.split(/ {2,}/)
case splits.length
when 2
puts "Address1 "+ splits[1]
when 3
puts "Address1 "+ splits[1]
puts "Address2 "+ splits[2]
else
end
end
But it fails for the following sample
leftSideHasData rightSideHasData
OnlyRightSideHasData
How can I achieve this in Ruby ? Does ruby provide any apis to do this with ease ?
text = %W{ Address1 Address2
adress1, adress1, # 34 , adress1,
4th Floor, Plot # 14 & 15,
Drive,, HARIKA BHIMANI
Madhapur, Hyderabad - 500081 2-14-117/35-1 Nas
Andhra Pradesh AP
+(91)40-00000000
xyz#dabc.com}
rows = text.split("\n").map { |row| row.split(/\s{2,}/) }
rows.each { |row| address1 << row[0]; address2 << row[1] }
address1
=> ["",
" adress1, adress1, # 34 , adress1, ",
" 4th Floor, Plot # 14 & 15, ",
" Drive,,",
" Madhapur, Hyderabad - 500081",
" Andhra Pradesh",
" +(91)40-00000000",
" xyz#dabc.com"]
address2
=> ["Address1", nil, nil, "HARIKA BHIMANI", "2-14-117/35-1 Nas", "AP", nil, nil]
You can remove nils with address2.compact

Resources