0

Below is the text file:

Old count: 56
S id: 1
M id: 1 
New count: 2
Old count: 56
S id: 1
M id: 2
New count: 20
Old count: 56
S id: 1
M id: 2
New count: 32
-----------------------------
Old count: 2
S id: 2
M id: 1
New count: 4
--------------------------------
.
.
.
.

I have used delimiter "---------------" for each ids.

How to parse the value such that the lines with in the delimiter "-----" that is new count is added like this: 2+20+32 = 54

Hash array: count << {'new count' => 54} for first block and so on for remaining blocks.

I have tried like this..

begin
f=File.open("out2", "r")
f.each_line do |line|
@data+=line
end

[email protected]("------")
s_rec.each do |rec|
row_s=rec.split(/\n/)

row_s.each do |row|

  if r.include?"New count"
    rv=row.split(":")
    @db=rv[1]
  end

  end
  end
2
  • Why is 69 not added? In your text, you have "New count" but you don't have 'new count'. Commented Apr 20, 2013 at 10:01
  • I am giving id as 'new count' in array while inserting Commented Apr 20, 2013 at 10:04

2 Answers 2

1

Not sure what output format you are trying to achieve, but given the text:

text = <<__
Old count: 56
S id: 1
M id: 1 
New count: 2
Old count: 56
S id: 1
M id: 2
New count: 20
Old count: 56
S id: 1
M id: 2
New count: 32
-----------------------------
Old count: 2
S id: 2
M id: 1
New count: 4
--------------------------------
.
.
.
.
__

this:

text
.split(/^-{5,}/)
.map{|s| s.scan(/\bNew count: (\d+)/).map{|match| match.first.to_i}.inject(:+)}

gives:

[
  54,
  4,
  nil
]


In response to the comment, still not clear what you want because what you wrote is not a valid Ruby object, but this:

text
.scan(/^S id: (\d+).+?^New count: (\d+)/m)
.inject(Hash.new(0)){|h, (k, v)| h[k.to_i] += v.to_i; h}
.map{|k, v| {"S id" => k, "new count" => v}}

gives:

[
  {
    "S id"      => 1,
    "new count" => 54
  },
  {
    "S id"      => 2,
    "new count" => 4
  }
]
Sign up to request clarification or add additional context in comments.

1 Comment

I am expecting output like this { 'S id'=>1, 'new count'=>54 } {'S id'=>2, 'new count'=>4}
0

I'd start with:

data = 'Old count: 56
S id: 1
M id: 1 
New count: 2
Old count: 56
S id: 1
M id: 2
New count: 20
Old count: 56
S id: 1
M id: 2
New count: 32
-----------------------------
Old count: 2
S id: 2
M id: 1
New count: 4
--------------------------------
'

ary = data.split("\n").slice_before(/^---/).map{ |a| a.select{ |s| s['New count:'] }.map{ |s| s[/\d+/].to_i }.inject(:+) }.compact

Which gives me an array:

[
    [0] 54,
    [1] 4,
]

compact is needed because there's a trailing ---- block delimiter that results in an empty array when slice_before does its magic.

From that point it's easy to create an array of hashes:

Hash[ ary.map.with_index(1) { |v, i| ["S #{ i }", "new count #{ v }" ] } ]

Which looks like:

{
    "S 1" => "new count 54",
    "S 2" => "new count 4"
}

Breaking it down, the code through slice_before returns:

[
    [0] [
        [ 0] "--------------------------------",
        [ 1] "Old count: 56",
        [ 2] "S id: 1",
        [ 3] "M id: 1 ",
        [ 4] "New count: 2",
        [ 5] "Old count: 56",
        [ 6] "S id: 1",
        [ 7] "M id: 2",
        [ 8] "New count: 20",
        [ 9] "Old count: 56",
        [10] "S id: 1",
        [11] "M id: 2",
        [12] "New count: 32"
    ],
    [1] [
        [0] "-----------------------------",
        [1] "Old count: 2",
        [2] "S id: 2",
        [3] "M id: 1",
        [4] "New count: 4"
    ]
]

From there it's straightforward, selecting the lines that are needed in each sub-array, extracting out the values, and summing them using inject.

Once that's done it's simply using map and with_index to build the string and name/value pairs, then let Hash turn them into a hash.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.