to_s method returning an unwanted "\" - arrays

I wrote a method that takes an array of numbers, adds the number 2 to it, and then returns an array of strings.
def add_two(array)
new_array = array.map{|x| "#{x} + 2 = #{x + 2}"}
new_array.to_s
end
The following is a test result:
I have an unwanted \ in my return. I am trying to figure out where the \ is coming from. Can someone point me in the right direction?

It is coming from to_s that you have at the end. You are converting an array of strings (which is presumably already what you want) into a single string that contains double quotations (which must be escaped by \). To fix it, just remove your line with to_s.

Its not adding extra \s. \ is escape character to escape " which is part of the result String. Here:
a = add_two(array)
# => "[\"1 + 2 = 3\", \"2 + 2 = 4\", \"3 + 2 = 5\"]"
puts a
# ["1 + 2 = 3", "2 + 2 = 4", "3 + 2 = 5"]
or directly:
puts add_two(array)
# ["1 + 2 = 3", "2 + 2 = 4", "3 + 2 = 5"]

Related

Add the last index of an array with a unique seperator

I am trying to get the last character of an array to join with it's own character. I'm having trouble trying to figure this out on my own I'm still unfamiliar with built in methods on ruby. Here's where I'm at so far:
def list(names)
#last = names.last
joined = names.map(&:values).flatten.join(", ")
#joined.pop
#joined << last.join(" &")
end
What I want to do is for the last index I want to join it with it's own character. I've tried doing this for hours but I keep getting errors. If anyone can point me in the right direction on this I would greatly appreciate it.
My target goal for an output would be
list([{name: 'Bart'},{name: 'Lisa'},{name: 'Garry'}])
to output:
"Bart, Lisa & Gary"
I suggest creating the string with all names separated by commas (e.g., "Bart, Lisa, Garry") and then replacing the last comma with " &". Here are two ways to do that.
Code
def list1(names)
all_commas(names).tap { |s| s[s.rindex(',')] = ' &' }
end
def list2(names)
all_commas(names).sub(/,(?=[^,]+\z)/, ' &')
end
def all_commas(names)
names.map(&:values).join(', ')
end
Example
names = [{ name: 'Bart' }, { name: 'Lisa' } , { name: 'Garry' }]
list1 names
#=> "Bart, Lisa & Garry"
list2 names
#=> "Bart, Lisa & Garry"
Explanation
The steps are as follows.
For all_commas:
a = names.map(&:values)
#=> [["Bart"], ["Lisa"], ["Garry"]]
a.join(', ')
#=> "Bart, Lisa, Garry"
For list1
s = all_commas(names)
#=> "Bart, Lisa, Garry"
i = s.rindex(',')
#=> 10
s[i] = ' &'
#=> " &"
s #=> "Bart, Lisa & Garry"
tap's block returns s
For list2
a = all_commas(names)
#=> "Bart, Lisa, Garry"
a.sub(/,(?=[^,]+\z)/, ' &')
# => "Bart, Lisa & Garry"
The regular expression, which employs a positive lookahead, reads, "match a comma, followed by one or more characters other than comma, followed by the end of the string".
Here's a solution that yields your desired output, given your input:
def list(names)
*head, tail = names.map(&:values)
[head.join(", "), tail].join(" & ")
end
Enjoy!
Here's a solution with the Oxford comma, which I prefer :)
def list(name_list)
*names, last = name_list.flat_map(&:values)
oxford_comma = names.size > 1 ? ", " : ""
names.join(", ") + oxford_comma + "& #{last}"
end
(Note: if this is Rails, Array#to_sentence does this automatically.)

How to navigate in an Array of strings left and right

I have an array of strings
var characters = ["Jim", "Anna", "Nick", "Chris", "Peter"];
my initial position is Jim[0]. if i type right i want to go to the next one
In this case to "Anna". I can do this by adding one to the current index.
The thing is getting more tricky when i type left from the initial position?
So how can i go from Jim[0] -> Peter[4]?
Something that works is
Jim[0] - 1 + characters.length which equals to 0 - 1 + 5 = 4
and this is Peter. But this seems incorrect because i cannot do that in the case that the current value is Anna[1] and i want to go to Jim[0]. As 1 - 1 + 5 = 5
Something like this would work.
var characters = ["Jim", "Anna", "Nick", "Chris", "Peter"];
var index = 0; // Currently at Jim.
var direction = -1; // 1 for right, -1 for left.
// What's left of our current position?
characters[(index + characters.length + direction) % characters.length]; // Peter!
You could do a conditional. Keep your index in a variable instead of hard-coding it. This will allow you to do something similar to the pseudocode following (Sorry, wasn't sure which language this was for):
new_index = index--
if (new_index < characters.length)
index = characters.length - 1
You can then use that determined index to access the array. You could something similar to wrap around going forwards as well.
There seems to be no single formula to calculate the left and right index without using conditions.
If you don't intend to use if-else or just want a single line solution, you can use the ternary operator as follows:
new_index = (direction=="left")?(index==0)?characters.length-1:index-1:(index==characters.length-1)?0:index+1
Please note that the above code assumes there are only 2 possible directions.
This is what you're looking for
(i % characters.length) + characters.length) % characters.length
var characters = ["Jim", "Anna", "Nick", "Chris", "Peter"];
var index;
for( var i = -10; i < 10; i++ ){
index = ((i % characters.length) + characters.length) % characters.length;
console.log(i + " > " + index + " = " + characters[index]);
}

Split by multiple delimiters in Ruby

I need to make an array from a string, and I have to use multiple delimiters (apart from the space):
! # $ # % ^ & * ( ) - = _ + [ ] : ; , . / < > ? \ |
I read here and here, and the solution seems to be to use:
my_string.split(/[\s!#$#%^&*()-=_+[]:;,./<>?\|]/)
This is the exercise:
Given a sentence, return an array containing every other word.
Punctuation is not part of the word unless it is a contraction.
In order to not have to write an actual language parser, there won't be any punctuation too complex.
There will be no " ' " that is not part of a contraction.
Assume each of these charactsrs are not to be considered:
! # $ # % ^ & * ( ) - = _ + [ ] : ; , . / < > ? \ |
Examples:
alternate_words("Lorem ipsum dolor sit amet.") # => ["Lorem", "dolor", "amet"]
alternate_words("Can't we all get along?") # => ["Can't", "all", "along"]
alternate_words("Elementary, my dear Watson!") # => ["Elementary", "dear"]
This is how I'm trying to do it:
def every_other_word(sentence)
my_words = []
words = sentence.split(/[\s!#$^&*()-=_+[\]:;,.\/#%<>?\|]/)
words.each_with_index do |w, i|
next if i.odd?
my_words << w
end
my_words
end
This is the error I get:
$ ruby ./session2/3-challenge/7_array.rb
./session2/3-challenge/7_array.rb:14: premature end of char-class: /[\s!#$^&*()-=_+[\]:;,.\/#%<>?\|]/
Most of the mentioned delimiting characters have special meaning in regular expression literals. For example, ] isn't the ] character but the end of a character class. The linked page should list all of them and explain their meaning.
Those characters need to be escaped in regular expression literals by preceding each with \. In this character class -, [, ], / and \ need to be escaped (^ only needs to if it's the first character and - only if it isn't the last character which it isn't):
/[\s!#$#%^&*()\-=_+\[\]:;,.\/<>?\\|]/
You can also let Ruby do the work with Regexp.escape (aka Regexp.quote). It escapes every special character but the resulting regular expression will be equivalent:
escaped_characters = Regexp.escape('!#$#%^&*()-=_+[]:;,./<>?\|')
/[\s#{escaped_characters}]/
By the way, \s isn't just space like within double-quoted string literals (a weird feature), it matches other ASCII whitespace characters too (\n, \t, \r, \f and \v).
You have been told there are no apostrophes and you are to disregard:
BADDIES = '!#$#%^&*()-=_+[]:;,./<>?\|'
so why not:
remove the BADDIES with String#ydelete;
split the string into words with String#split;
group the words in pairs with Enumerable#each_slice; and
select the first word of each pair Enumerable#first and Enumerable#map.
We can write:
str = "Now it the time for all good Rubiests to come to the aid of their " +
"fellow coders (except for Bob)! Is that not true?"
str.delete(BADDIES).split.each_slice(2).map(&:first)
#=> ["Now", "the", "for", "good", "to", "to", "aid", "their",
# "coders", "for", "Is", "not"]
Look, Ma! No regex!

Append a string to variable during array creation

I'm attempting to create a very simple array in TCL but I can't figure out the syntax to make it append text to a variable in an assignment. Here is what I am trying to do:
set var1 "some text"
set var2 "other text"
array set arrValues {
1 $var1 + _text
2 $var2 + _text
3 $var1 + _different_text
4 $var1 + _different_text
}
How do I tell it that it should treat $var1 + _text as the data that needs to get inserted without needing to make another variable outside of the array?
Since you want to substitute the variables, you can't use {braces} to declare the array elements:
$ tclsh
% set var1 "some text"
some text
% set var2 "other text"
other text
% array set arrValues {1 ${var1}_text 2 ${var2}_text 3 ${var1}_different_text 4 ${var2}_different_text}
% parray arrValues
arrValues(1) = ${var1}_text
arrValues(2) = ${var2}_text
arrValues(3) = ${var1}_different_text
arrValues(4) = ${var2}_different_text
% array set arrValues [list 1 ${var1}_text 2 ${var2}_text 3 ${var1}_different_text 4 ${var2}_different_text]
% parray arrValues
arrValues(1) = some text_text
arrValues(2) = other text_text
arrValues(3) = some text_different_text
arrValues(4) = other text_different_text
You can just join the string together... But so it knows where the variable name ends, put it in braces ${var1}_text... And so your array values get evaluated, put them in quotes instead of braces, or use [list a b c]
(Please excuse lack of format - answering from my phone)
The simplest robust way is probably to use the list command to construct the thing to use with array set:
set var1 "some text"
set var2 "other text"
array set arrValues [list \
1 "$var1 + _text" \
2 "$var2 + _text" \
3 "$var1 + _different_text" \
4 "$var1 + _different_text"
]
That's assuming that you want just the variable substituted. ("${var1}_text" might be more suitable for your specific case; you can build the value to insert using any Tcl substitutions you want.) However, in this case I'd actually just do this instead:
set var1 "some text"
set var2 "other text"
set arrValues(1) "$var1 + _text"
set arrValues(2) "$var2 + _text"
set arrValues(3) "$var1 + _different_text"
set arrValues(4) "$var1 + _different_text"
It's shorter. The array set command only really becomes useful when you are using literal dictionaries as the source of what to set, or when you're taking a serialized value generated elsewhere entirely (e.g., from an array get in another context).

Operate on 1D arrays in gnuplot

How to do something equivalent to this:
In: A = [ 1 2 3 ]
In: B = 2 * A
In: B
Out: [ 2 4 6 ]
This method gets part of the way:
In: do for [i in "1 2 3"] { print 2*i }
Out:
2
4
6
But I want to return another list/array that can be used in further operations.
As you already found out, using space-delimited words is the only way to simulate arrays. So you must format the output again as a string in which the single entries are separated by spaces:
out = ''
do for [i in "1 2 3"] {
out = out . sprintf('%d ', 2*i)
}
print sprintf('%d entries: %s', words(out), out)
This prints
3 entries: 2 4 6
If using floats, you must use e.g. '%f' to format the output:
out = ''
do for [i in "1.1 2.2 3.3"] {
out = out . sprintf('%f ', 2*i)
}
print sprintf('%d entries: %s', words(out), out)
words counts the words in a string, and you can use word to extract a certain word from the string (starting from 1):
print word(out, 2)
4

Resources