How to use variable of condition inside the block - ruby

How can I use the var string of the condition in the return value?
lines = ["dyfögifuödxfghif", "xdghödfx", "abcdefg"]
strings = ["abc", "zzzzzzzzz"]
lines.each do |line|
if strings.any? { |string| line.include?(string) }
return string
end
end
return nil
Datatypes:
lines:Array, line:String, strings:Array, string:String
Desired result:
=> "abc"
I am iterating through a lot of lines and want to check each of them if they include a string inside the array named strings -> until I either find a match, or finished iterating.
This snippet does work, but it does the same thing twice:
lines.each do |line|
if strings.any? { |string| line.include?(string) }
return strings.detect { |string| line.include?(string) }
end
end
return nil

You could use detect:
return strings.detect { |string| lines.any? { |line| line.include?(string) } }

You could use .find with some regex to bring back the first match
strings.find {|word| lines.find {|line| line =~ /#{word}/ } }
=> "abc"
# if you want all matches
strings.select {|word| lines.find {|line| line =~ /#{word}/ } }
=> ["abc"]

If you want the first match:
strings.detect { |string| line.include?(string) }
If you want all matches (in an array):
strings.select { |string| line.include?(string) }

You can do this pretty easily if you compile the list of strings to match into a compact regular expression:
string_rx = Regexp.union(strings)
Then all you have to do is filter out the lines that match and pull off the first one:
lines.grep(string_rx).first
# => "abcdefg"
If you don't want to have to process the entire array and optimize this for performance:
lines.lazy.grep(string_rx).first
# => "abcdefg"
The lazy designator makes each entry flow through the chain to completion rather than each stage buffering up before passing to the next.

Related

How to use gsub with a file in Ruby?

Hey I've a little problem, I've a string array text_word and I want to replace some letters with my file transform.txt, my file looks like this:
/t/ 3
/$/ 1
/a/ !
But when I use gsub I get an Enumerator back, does anyone know how to fix this?
text_transform= Array.new
new_words= Array.new
File.open("transform.txt", "r") do |fi|
fi.each_line do |words|
text_transform << words.chomp
end
end
text_transform.each do |transform|
text_word.each do |words|
new_words << words.gsub(transform)
end
end
You can see String#gsub
If the second argument is a Hash, and the matched text is one of its
keys, the corresponding value is the replacement string.
Also you can use IO::readlines
File.readlines('transform.txt', chomp: true).map { |word| word.gsub(/[t$a]/, 't' => 3, '$' => 1, 'a' => '!') }
gsub returns an Enumerator when you provide just one argument (the pattern). If you want to replace just add the replacement string:
pry(main)> 'this is my string'.gsub(/i/, '1')
"th1s 1s my str1ng"
You need to refactor your code:
text_transform = Array.new
new_words = Array.new
File.open("transform.txt", "r") do |fi|
fi.each_line do |words|
text_transform << words.chomp.strip.split # "/t/ 3" -> ["/t/", "3"]
end
end
text_transform.each do |pattern, replacement| # pattern = "/t/", replacement = "3"
text_word.each do |words|
new_words << words.gsub(pattern, replacement)
end
end

Trying to remove punctuation without using regex

I am trying to remove punctuation from an array of words without using regular expression. In below eg,
str = ["He,llo!"]
I want:
result # => ["Hello"]
I tried:
alpha_num="abcdefghijklmnopqrstuvwxyz0123456789"
result= str.map do |punc|
punc.chars {|ch|alpha_num.include?(ch)}
end
p result
But it returns ["He,llo!"] without any change. Can't figure out where the problem is.
include? block returns true/false, try use select function to filter illegal characters.
result = str.map {|txt| txt.chars.select {|c| alpha_num.include?(c.downcase)}}
.map {|chars| chars.join('')}
p result
str=["He,llo!"]
alpha_num="abcdefghijklmnopqrstuvwxyz0123456789"
Program
v=[]<<str.map do |x|
x.chars.map do |c|
alpha_num.chars.map.include?(c.downcase) ? c : nil
end
end.flatten.compact.join
p v
Output
["Hello"]
exclusions = ((32..126).map(&:chr) - [*'a'..'z', *'A'..'Z', *'0'..'9']).join
#=> " !\"\#$%&'()*+,-./:;<=>?#[\\]^_`{|}~"
arr = ['He,llo!', 'What Ho!']
arr.map { |word| word.delete(exclusions) }
#=> ["Hello", "WhatHo"]
If you could use a regular expression and truly only wanted to remove punctuation, you could write the following.
arr.map { |word| word.gsub(/[[:punct:]]/, '') }
#=> ["Hello", "WhatHo"]
See String#delete. Note that arr is not modified.

Filter through a text file

I want to sort through a text file and leave only a certain section. I have this text in the text file:
{
"id"=>”0000001”,
"type"=>”cashier”,
"summary"=>”Henock”,
"self"=>"https://google.com/accounts/0000001”,
"html_url"=>"https://google.com/accounts/0000001”
}
{
"id"=>”0000002”,
"type"=>”cashier”,
"summary"=>”Vic”,
"self"=>"https://google.com/accounts/0000002”,
"html_url"=>"https://google.com/accounts/0000002”
}
{
"id"=>”0000003”,
"type"=>”cashier”,
"summary"=>”Mo”,
"self"=>"https://google.com/accounts/0000003”,
"html_url"=>"https://google.com/accounts/0000003”
}
How would I sort it so that only the information with person "Mo" is shown?
This is what I tried:
somefile.readlines("filename.txt").grep /Mo}/i
but it is useless.
Code
def retrieve_block(fname, summary_target)
arr = []
File.foreach(fname) do |line|
next if line.strip.empty?
arr << line
next unless arr.size == 7
return arr.join if arr[3].match?(/\"summary\"=>\"#{summary_target}\"/)
arr = []
end
end
Example
Let's first create a file.
text =<<_
{
"id"=>"0000001",
"type"=>"cashier",
"summary"=>"Henock",
"self"=>"https://google.com/accounts/0000001",
"html_url"=>"https://google.com/accounts/0000001"
}
{
"id"=>"0000003",
"type"=>"cashier",
"summary"=>"Mo",
"self"=>"https://google.com/accounts/0000003",
"html_url"=>"https://google.com/accounts/0000003"
}
_
All of the keys and values represented in this string are surrounded with double-quotes. In the question however, many of these keys and values are surrounded by special characters that have a superficial appearance of a double quote. I have assumed that those characters would be converted to double quotes in a pre-processing step.
FName = "test"
File.write(FName, text)
#=> 325
puts retrieve_block(FName, "Mo")
{
"id"=>"0000003",
"type"=>"cashier",
"summary"=>"Mo",
"self"=>"https://google.com/accounts/0000003",
"html_url"=>"https://google.com/accounts/0000003"
}
This should work because of the consistent format of the file.
To return a hash, rather than a string, a slight modification is required.
def retrieve_block(fname, summary_target)
h = {}
File.foreach(fname) do |line|
line.strip!
next if line.empty? || line == '{'
if line == '}'
if h["summary"] == summary_target
break h
else
h = {}
end
else
k, v = line.delete('",').split("=>")
h[k] = v
end
end
end
retrieve_block(FName, "Mo")
#=> {"id"=>"0000003",
# "type"=>"cashier",
# "summary"=>"Mo",
# "self"=>"https://google.com/accounts/0000003",
# "html_url"=>"https://google.com/accounts/0000003"}

how I could do a gsub with array elements?

How I could replaces a string like this
I think something like this
inputx.gsub(/variable1/,string1.split(";")[i])
But I dont know How I could do this code
name1;variable1
name;variable1
name3;variable1
by
dog;watch;rock
For obtain this
name1;dog
name;watch
name3;rock
string1 => dog;watch;rock ; this string Im trying to split for replace each string variable1
Please help me
subst = "dog;watch;rock".split ';'
input.gsub(/variable1/) do subst.shift end
#⇒ "name1;dog \n name;watch \n name3;rock"
Given (assuming) this input:
inputx = <<-EOD
name1;variable1
name;variable1
name3;variable1
EOD
#=> "name1;variable1\nname;variable1\nname3;variable1\n"
string1 = 'dog;watch;rock'
#=> "dog;watch;rock"
You can chain gsub and with_index to perform a replacement based on its index:
inputx.gsub('variable1').with_index { |_, i| string1.split(';')[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
You could also perform the split beforehand:
values = string1.split(';')
#=> ["dog", "watch", "rock"]
inputx.gsub('variable1').with_index { |_, i| values[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
I'm not sure there's a way to do it using .gsub(). One simple way to achieve what you want to is the following:
str = "dog;watch;rock"
array = str.split(";")
array.each_with_index do |str, i|
array[i] = "name#{i + 1};#{str}"
end
puts array
Output:
name1;dog
name2;watch
name3;rock
file intro2 => dog;watch;rock
file intro
name1;variable1
name;variable1
name3;variable1
ruby code
ruby -e ' n=0; input3= File.read("intro");string1= File.read("intro2") ;input3x=input3.gsub("variable1") { val =string1.split(";")[n].to_s; n+=1; val } ;print input3x' >gggf

Confused about Ruby length property

Why is the my foo() function printing out the string "YAAR" as having a length of 5?
def foo()
map = Hash.new
File.open('dictionary.txt').each_line{ |s|
word = s.split(',')
if word.any? { |b| b.include?('AA') }
puts word.last
puts word.last.length
end
}
end
someFile.txt
265651,YAAR
265654,YAARS
output
YAAR
5
YAARS
6
You're getting a newline '\n' at the end of both strings. So, your split is receiving:
"265651,YAAR\n"
"265654","YAARS\n"
reading from a file you'll get a new line char (\n) at the end of all the lines (except maybe the last one)
instead of
word = s.split(',')
in your loop, use this
word = s.split(',').map { |s| s.chomp }

Resources