28

I have an array with unique elements. Is there a way to replace a certain value in it with another value without using its index value?

Examples:

array = [1,2,3,4]
if array.include? 4
#  "replace 4 with 'Z'"
end
array #=> [1,2,3,'Z']

hash = {"One" => [1,2,3,4]}
if hash["One"].include? 4
#  "replace 4 with 'Z'"
end
hash #=> {"One" => [1,2,3,'Z']}
4
  • What are you looking for here: array = [1,4,4]; if array.include? 4 # replace 4 with 'Z'? Commented Oct 16, 2014 at 23:42
  • @CarySwoveland Yes, I just need to replace the 4(s) with another element of my choice. [1,4,4] => [1,'Z','Z'] Commented Oct 16, 2014 at 23:46
  • I thought only the first of such instances should be replaced since the title says "single element". But it turns out not. Commented Oct 16, 2014 at 23:46
  • 1
    @sawa None of my arrays will have repeating elements so it won't matter. Commented Oct 16, 2014 at 23:47

4 Answers 4

44
p array.map { |x| x == 4 ? 'Z' : x }

# => [1, 2, 3, 'Z']
Sign up to request clarification or add additional context in comments.

4 Comments

Why go through the entire array if the first element equals 4?
How do you know '4' is only in the array once?
From the question: "I have an array with unique elements"
you should add ! to persist the value in the array array.map! { |x| x == 4 ? 'Z' : x }
20

You can do it as:

array[array.index(4)] = "Z"

If the element is not necessarily in the array, then

if i = array.index(4)
  array[i] = "Z"
end

4 Comments

He said he didn't want to use the item's index value.
While I agree with you, I think your comment is a bit harsh.
@MarkThomas Maybe. But I suspect the post was accompanied with a downvote, which made it worse.
You don't have to suspect. Why do you think my down vote justifies your reaction? All it means is I won't bother to offer an explanation in the future.
11

You can use Array#map

array = array.map do |e|
  if e == 4
    'Z'
  else
    e
  end
end

to edit the array in place, rather than creating a new array, use Array#map!

If you have more than one thing you want to replace, you can use a hash to map old to new:

replacements = {
  4 => 'Z',
  5 => 'five',
}
array = array.map do |e|
  replacements.fetch(e, e)
end

This make uses of a feature of Hash#fetch, where if the key is not found, the second argument is used as a default.

2 Comments

What if my array is in a hash like in the Update?
@Lasonic Then: hash['key'].map! do |e| ... end
2

A very simple solution that assumes there will be no duplicates and that the order doesn't matter:

hash = { 'One' => [1, 2, 3, 4] }

hash['One'].instance_eval { push 'Z' if delete 4 }

instance_eval sets the value of self to the receiver (in this case, the array [1,2,3,4]) for the duration of the block passed to it.

8 Comments

What if it's not the last element in the array?
I'd not do it that way, but it is interesting. Perhaps we have a rogue downvoter in our midst.
@Lasonic, if order is important, I believe Wayne's solution is better. It will replace all occurrences of 4 with 'Z', maintaining their original order, and without using any indexes.
To grant that the array will continue with no duplicates you can use hash['One'].instance_eval { push('Z').uniq! if delete 4 } . :)
@BKSpurgeon, instance_eval does not modify the receiver or its class in any way. The Array class is not modified. All it does is set the value of self to the receiver, and this modification is local to the block passed to it.
|

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.