Duplicating a Ruby array of strings
Your second solution can be shortened to arr2 = arr.map do |e| e.dup end
(unless you actually need the behaviour of clone
, it's recommended to use dup
instead).
Other than that your two solutions are basically the standard solutions to perform a deep copy (though the second version is only one-level deep (i.e. if you use it on an array of arrays of strings, you can still mutate the strings)). There isn't really a nicer way.
Edit: Here's a recursive deep_dup method that works with arbitrarily nested arrays:
class Array
def deep_dup
map {|x| x.deep_dup}
end
end
class Object
def deep_dup
dup
end
end
class Numeric
# We need this because number.dup throws an exception
# We also need the same definition for Symbol, TrueClass and FalseClass
def deep_dup
self
end
end
You might also want to define deep_dup for other containers (like Hash), otherwise you'll still get a shallow copy for those.
Ruby method that takes a string and returns an array of duplicates capitalizing the next letter in the string in each duplicate (like a wave)
I would do this:
def wave(word)
words = Array.new(word.size) { word.dup }
words.map.with_index { |e, i| e[i] = e[i].upcase; e } - [word]
end
wave("hello")
#=> ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
wave("two words")
#=> ["Two words", "tWo words", "twO words", "two Words", "two wOrds", "two woRds", "two worDs", "two wordS"]
Cloning an array with its content
You need to do a deep copy of your array.
Here is the way to do it
Marshal.load(Marshal.dump(a))
This is because you are cloning the array but not the elements inside. So the array object is different but the elements it contains are the same instances. You could, for example, also do a.each{|e| b << e.dup}
for your case
ruby array of arrays get duplicate string array
Just count all sites with each_with_object
:
array.each_with_object(Hash.new(0)) {|(site, count), memo| memo[site] += count}
#=> {"twitter.com"=>64, "google.com"=>25,
# "paypal.me"=>11, "yahoo.com"=>12, "youtube.com"=>31}
You can simply convert the result to array by adding to_a
, but IMO hash is enough for your issue.
Use [].replace to make a copy of an array
This is the tricky concept of mutability in ruby. In terms of core objects, this usually comes up with arrays and hashes. Strings are mutable as well, but this can be disabled with a flag at the top of the script. See What does the comment "frozen_string_literal: true" do?.
In this case, you can call dup
, deep_dup
, clone
easily to the same effect as replace
:
['some', 'array'].dup
['some', 'array'].deep_dup
['some', 'array'].clone
Marshal.load Marshal::dump(['some', 'array'])
In terms of differences, dup
and clone
are the same except for some nuanced details - see What's the difference between Ruby's dup and clone methods?
The difference between these and deep_dup
is that deep_dup
works recursively. For example if you dup a nested array, the inner array will not be cloned:
a = [[1]]
b = a.clone
b[0][0] = 2
a # => [[2]]
The same thing happens with hashes.
Marshal.load Marshal::dump <object>
is a general approach to deep cloning objects, which, unlike deep_dup
, is in ruby core. Marshal::dump
returns a string so it can be handy in serializing objects to file.
If you want to avoid unexpected errors like this, keep a mental index of which methods have side-effects and only call those when it makes sense to. An explanation point at the end of a method name indicates that it has side effects, but others include unshift, push, concat, delete, and pop. A big part of fuctional programming is avoiding side effects. You can see https://www.sitepoint.com/functional-programming-techniques-with-ruby-part-i/
Find a Duplicate in an array Ruby
Array#difference
comes to the rescue yet again. (I confess that @user123's answer is more straightforward, unless you pretend that Array#difference
is already a built-in method. Array#difference
is probably the more efficient of the two, as it avoids the repeated invocations of count
.) See my answer here for a description of the method and links to its use.
In a nutshell, it differs from Array#- as illustrated in the following example:
a = [1,2,3,4,3,2,4,2]
b = [2,3,4,4,4]
a - b #=> [1]
a.difference b #=> [1, 3, 2, 2]
One day I'd like to see it as a built-in.
For the present problem, if:
arr = [1,2,3,4,3,4]
the duplicate elements are given by:
arr.difference(arr.uniq).uniq
#=> [3, 4]
Duplicate array elements in Ruby
How about
rangers.zip(rangers).flatten
using Array#zip
and Array#flatten
?
A solution that might generalize a bit better for your second request might be:
rangers.flat_map { |ranger| [ranger] * 2 }
using Enumerable#flat_map
.
Here you can just replace the 2
with any value or variable.
Ruby - Iterate through each string inside an array and remove repeated characters
Input
array = ["abc", "abc", "xxzzyyww", "aaaaa"]
Code
p array.map { _1.chars.uniq.join }
Output
["abc", "abc", "xzyw", "a"]
How do I detect duplicate values within an array in Ruby?
You can create a hash to store number of times any element is repeated. Thus iterating over array just once.
h = Hash.new(0)
['a','b','b','c'].each{ |e| h[e] += 1 }
Should result
{"a"=>1, "b"=>2, "c"=>1}
Related Topics
What Is the Most Ruby-Ish Way of Accessing Nested Hash Values at Arbitrary Depths
Upgrading to Ruby 2.1.3 on MAC Osx 10.9.5
How to Find All Modules and Classes Within a Module, Recursively
How to Use Activesupport::Configurable with Rails Engine
How to Use Mongodb Ruby Driver to Do a "Group" (Group By)
Ruby Google_Drive Gem Oauth2 Saving
Exception_Notification for Delayed_Job
Ubuntu 12.10 - Ruby Gem Rmagick Missing Dependency Issue
Running into Issues with Rvm During Ruby Install (1.9.2)
Displaying a Polygon with Gmaps4Rails
Zentest Autotest Not Running Tests
How to Use Escape Characters in Strings
How to Update Rails Locale Yaml File Without Loosing Comments and Variables
Commonmarker Gem Cannot Be Installed (Needed for Jekyll) MACos