2

What I need to do is convert something like this:

"id,name,user[id,email]"

into this array:

["id", "name", {"user"=>["id", "email"]}] 

What is the best way to do that? I think some function like split or scan can help, but I don't have much knowledge in regex to solve this.

4
  • Your expected array is invalid. Commented Apr 29, 2015 at 13:52
  • What is the context? I think if you provide a bit more background on what you are trying to do, it might help. Commented Apr 29, 2015 at 13:55
  • @sawa Edited it to be more appropriated. Ruby converts ["id", "name", "user" => ["id", "email"]] to ["id", "name", {"user"=>["id", "email"]}]. In the example, user became a hash inside the array. You can try it typing my original array in console. Commented Apr 29, 2015 at 13:56
  • @steveklein I'm receiving a string in this pattern by query string on request, need to convert it to an array to I can use this data. Commented Apr 29, 2015 at 13:58

2 Answers 2

3

Just out of curiosity:

▶ str = "id,name,user[id,email]"
▶ eval "[#{str.gsub(/(\w+)\[(.*?)\]/, '{\1=>[\2]}').gsub(/\w+/, ':\0')}]"
#⇒ [
#  [0] :id,
#  [1] :name,
#  [2] {
#    :user => [
#      [0] :id,
#      [1] :email
#    ]
#  }
#]

Disclamer: to use eval in production one must understand risks.

UPD Safe evaling (note that every ASCII \w symbol is converted to it’s wide pair from UTF-8 to prevent injection; not the best way around, but it works nicely unless you have ruby functions named with wide characters):

▶ safe = str.gsub(/\w/) do |e| 
▷   e.each_codepoint.map do |cp| 
▷     cp + 0xFF00 - 0x0020
▷   end.pack('U')
▷ end
#⇒ "id,name,user[id,email]"
▶ eval "[#{safe.gsub(/(\p{L}+)\[(.*?)\]/, '{\1=>[\2]}').gsub(/\p{L}+/, ':\0')}]"
#⇒ [
#  [0] :id,
#  [1] :name,
#  [2] {
#    :user => [
#      [0] :id,
#      [1] :email
#    ]
#  }
#]

Now you are free to turn keys back from wide characters to ASCII.

Sign up to request clarification or add additional context in comments.

10 Comments

Can I do exactly this without eval?
When I do eval on safe I'm getting: undefined local variable or method name'`
This error happens just in rails, on irb it does not happen. Will figure it out. Thanks.
You are welcome. This code probably requires some polishing, e.g. @ may appear in email etc, it should be considered as a proof of concept only.
\w would not work with wides neither in rails nor in plain ruby. There is \p{L} matcher for utf-8 word characters. ruby-doc.org/core-2.2.1/…
|
0
string = "id,name,user[id,email]"
parts = string.split(/[\,,\[,\]]/)
[parts[0], parts[1], {parts[2] => [parts[3], parts[4]]}]

You may also want to have some validation or not use all the parts if the first id is supposed to be the same as the second.

5 Comments

In my example case works. But what if I had "user[id,email],id,name"? The order can change, the number of strings can change, everything can change, my example is just a pattern. The @mudasobwa answer solves my problem but I did not want to use eval.
Why is it that "order can change, the number of strings can change, everything can change"?
@WilliamWeckl BTW, eval is not an evil. It might be used when you understand the circumstances. Absolutely safe usage: convert all \w to some utf-8, like wide characters ⇒ do eval ⇒ convert everything back.
@BSeven Because I'm receiving this by a query string in a request. In my request I'm saying what attributes I want to be returned in response but some attributes have nested inside.
@mudasobwa I'm sorry but I did not understand how can I do this: convert all \w to some utf-8, like wide characters ⇒ do eval ⇒ convert everything back

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.