Newbie question


#1

Given an array like

["&abc", “a&cb”, “b&ac”, “ccc”, “cb&a”]

what is the Ruby way to construct an array containing only elements with
duplicate characters following the &'s? In this case

["&abc", “b&ac”, “cb&a”]


#2

2006/5/5, Kyle A. removed_email_address@domain.invalid:

Given an array like

["&abc", “a&cb”, “b&ac”, “ccc”, “cb&a”]

what is the Ruby way to construct an array containing only elements with
duplicate characters following the &'s? In this case

["&abc", “b&ac”, “cb&a”]

You can use select or inject. However it’s not clear to me what you
mean by “duplicate characters following the &'s”. Can you elaborate?

robert


#3

On May 5, 2006, at 7:27 AM, Kyle A. wrote:

Given an array like

["&abc", “a&cb”, “b&ac”, “ccc”, “cb&a”]

what is the Ruby way to construct an array containing only elements
with
duplicate characters following the &'s? In this case

["&abc", “b&ac”, “cb&a”]

["&abc", “a&cb”, “b&ac”, “ccc”, “cb&a”].grep(/&…/)
=> ["&abc", “a&cb”, “b&ac”]

Hope that helps.

James Edward G. II


#4

James G. wrote:

["&abc", “a&cb”, “b&ac”, “ccc”, “cb&a”].grep(/&…/)
=> ["&abc", “a&cb”, “b&ac”]

Hope that helps.

That’s not quite it. That seems to match all strings containing an
ampersand followed by 2 other characters. What I need is all strings
that have duplicate characters following an & (&a in the above).
Something a little more concrete:

["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”, “&Help”]

would return

["&Edit", “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”]

(&e and &r are found multiple times).


#5

Kyle A. wrote:

that have duplicate characters following an & (&a in the above).
Something a little more concrete:

["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”, “&Help”]

would return

["&Edit", “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”]

(&e and &r are found multiple times).

keys = {}

["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”,
“&Help”].each do |l|
l =~ /&(.)/
(keys[ $1.downcase ] ||= []) << l
end

keys.values.select{|l| l.length > 1}.flatten

There’s almost certainly a better way…


#6

What he’s saying is that he wants both “&Edit” and “Vi&ew” to show up
because both have an ‘e’ after the ampersand.

I take it these are identifiers for Windows menus or the like, so the
character after the ampersand has to be unique within a particular
set.


#7

Here’s a quick attempt:

x = ["&Edit", “P&roject”, “Noamp”, “Vi&ew”, “S&ample”, “T&ree”]
y = Hash.new { |h,k| h[k] = Array.new }

x.each do |s|
if m = /&(.)/.match(s)
y[m[1].downcase] << s
end
end

y.values.select { |v| v.size > 1 }.flatten

=> ["&Edit", “Vi&ew”, “P&roject”, “T&ree”]


#8

On May 5, 2006, at 2:06 PM, Kyle A. wrote:

["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”,
“&Help”]

would return

["&Edit", “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”]

(&e and &r are found multiple times).

No letters are duplicated in “&Edit”.

I clearly don’t understand your goal, but you solve it like this:

array_of_strings.select do |string|

put test against string here…

end

Sorry I am not more help.

James Edward G. II


#9

2006/5/5, Kyle A. removed_email_address@domain.invalid:

James G. wrote:

["&abc", “a&cb”, “b&ac”, “ccc”, “cb&a”].grep(/&…/)
=> ["&abc", “a&cb”, “b&ac”]

Hope that helps.

That’s not quite it. That seems to match all strings containing an
ampersand followed by 2 other characters. What I need is all strings
that have duplicate characters following an & (&a in the above).

By your definition “a&cb” does not belong into the result set.

Something a little more concrete:

["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”, “&Help”]

would return

["&Edit", “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”]

(&e and &r are found multiple times).

Just for the fun of it:

irb(main):037:0> a=["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”,
“Favo&rites”, “&Help”]
=> ["&File", “&Edit”, “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”,
“&Help”]

irb(main):038:0> a.inject(Hash.new {|h,k| h[k]=[]}) do |h,str|
irb(main):039:1* /&(.)/ =~ str and h[$1.downcase[0]] << str
irb(main):040:1> h
irb(main):041:1> end.values.select {|v| v.size > 1}.flatten
=> ["&Edit", “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”]

irb(main):042:0> a.inject(Hash.new {|h,k| h[k]=[]}) do |h,str|
irb(main):043:1* /&(.)/ =~ str and h[$1.downcase[0]] << str
irb(main):044:1> h
irb(main):045:1> end.inject([]){|res,(k,v)| res.concat v if v.size >
1;res }
=> ["&Edit", “Vi&ew”, “P&roject”, “T&ree”, “Favo&rites”]

Did I mention that inject is great?

:-))

robert