0

I like to parse string array and update value, what i have for example:

list= ["beam=0", "active=0", "rate=11", "version=4.1", "delay=5"]

in the above list i want to search for "active" and edit its value, like if "active=0" i want to make it "active=1" , and if its "active=1" i want to make it "active=0".

What i am doing is , but its not correct ,, can someone assist in this:

list.each do |lists|
   if lists.include?("active=0")
      lists = "active=1"
   elsif list.include?("active=1")
      lists = "active=0"
   end
end

what i expect in the end if list contains active=0 , than output list = ["beam=0", "active=1", "rate=11", "version=4.1", "delay=5"] and if list contains active=1, then output list = ["beam=0", "active=0", "rate=11", "version=4.1", "delay=5"]

1
  • Why not use a hash, e.g. hash = { beam: 0, active: 0, rate: 11, version: "4.1", delay: 5 }. That way you could update via hash[:active] = 1. Commented Nov 29, 2022 at 10:18

3 Answers 3

1

If you can use a hash, it is much more suitable for this task.

If you cannot, then the problem with your code is that you are not updating the original value. You are just updating the variable used in the #each iterator.

One way to do what you want is this:

list = ["beam=0", "active=0", "rate=11", "version=4.1", "delay=5"]

# convert to hash
hash = list.to_h { |x| x.split '=' }

# update any hash value
hash['active'] = hash['active'] == '0' ? '1' : '0'

# convert back to array
result = hash.map { |x| x.join '=' }

and, if for some reason, you wish to stay as close as possible to your original code, then you can use map instead of each. I do not recommend the below code for this case, since this is not good coding, but in case you have your reasons and this is for educational purposes only:

list = ["beam=0", "active=0", "rate=11", "version=4.1", "delay=5"]
result = list.map do |item|
  case item
  when 'active=0' then 'active=1'
  when 'active=1' then 'active=0'
  else
    item
  end
end
Sign up to request clarification or add additional context in comments.

7 Comments

I am getting this error, i am using ruby version 2.7.5 , "Failure/Error: hash = lines.to_h { |x| x.split '=' } ArgumentError: wrong array length at 84 (expected 2, was 3) "
@Abr that's because one of the strings contains more than one =. You can limit split to 2 substrings via x.split('=', 2)
I see that some string contains, "name=sit::sit_id::" , "IP=192.165.0.1" and "test=nt1,nt2," , is this triggering error? error : Failure/Error: hash = lines.to_h { |x| x.split('=', 2)} NoMethodError: undefined method `to_h' for #<String:0x0000557634649538> Did you mean? to_f to_r to_i to_s to_d to_c
@Abr the ArgumentError is caused by a string containing two = characters. It's the element at index 84 of your array. The other NoMethodError is unrelated to that problem. It occurred because you (accidentally) called to_h on a string.
ok i see, i changed limit but it seems one of string even dont contain "=", how you handle this? Failure/Error: hash = lines.to_h { |x| x.split('=', 2) } ArgumentError: wrong array length at 93 (expected 2, was 0)
|
0

You can iterate through the list and replace the number after active= like below:

list= ["beam=0", "active=0", "rate=11", "version=4.1", "delay=5"]

list.each_with_index do |item, index|
  next unless item.starts_with?('active')

  number_with_active = item.split('active=')[1].to_i
  list[index] = "active=#{(number_with_active+1)%2}"
end

Comments

0

I would actually suggest an entirely different approach; HOWEVER, the main problem with your original code is that you're using an inappropriate method right at the start. each isn't returning a modified array. Try using map instead. At a minimum, you'll also want to add a line of code to ensure all other elements return unchanged. If you don't, the other elements will be replaced with nil values. Here's what your code might look like with minimal modifications:

list= ["beam=0", "active=0", "rate=11", "version=4.1", "delay=5"]

list.map do |lists|
   if lists.include?("active=0")
      lists = "active=1"
   elsif list.include?("active=1")
      lists = "active=0"
   else
      lists
   end
end

#=>  ["beam=0", "active=1", "rate=11", "version=4.1", "delay=5"]

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.