for slicing an array, we can use
2.0.0p247 :021 > arr = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
2.0.0p247 :022 > arr.each_slice(3).to_a
=> [[1, 2, 3], [4, 5]]
2.0.0p247 :034 > arr # does not change array
=> [1, 2, 3, 4, 5]
i want to take only first part of sliced array, so i did it in the following way
2.0.0p247 :029 > arr = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
2.0.0p247 :030 > arr[0..2]
=> [1, 2, 3]
2.0.0p247 :031 > arr # does not change array
=> [1, 2, 3, 4, 5]
but it return a new array, and i want to do it in such a way that i can take a part of array in the same array without creating a new array
As in Ruby there are some methods of changing same array by putting a '!' sign as - sort!,reject! etc
Is there any method of doing this?
Given
array = [1,2,3,4,5]
To return array=[1,2,3], you can:
Slice! off the last half, so you return the first half.
array.slice!(3..5)
Return the first three elements and assign it to the variable.
array = array.first 3
Or
array = array[0..2]
...Or use a number of other array methods.
Do you mean slice! as found in the ruby docs?:
1.9.3p392 :001 > ar = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
1.9.3p392 :002 > ar.slice!(0,2)
=> [1, 2]
1.9.3p392 :003 > ar
=> [3, 4, 5]
Related
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
diff a ruby string or array
I have an old array: [1, 2, 3, 4, 5], and new: [1, 2, 4, 6]
How to get difference with Ruby: that 5, 3 was removed and 6 was added?
irb(main):001:0> a = [1, 2, 3, 4, 5]
=> [1, 2, 3, 4, 5]
irb(main):002:0> b = [1, 2, 4, 6]
=> [1, 2, 4, 6]
irb(main):003:0> a - b
=> [3, 5]
irb(main):005:0> b - a
=> [6]
irb(main):006:0>
I have an array of the form [1,2,3,4,5].
Is it possible to loop through this array and during each iteration get an array where the starting point is the current element and the end point is the element before that?
Like
[1,2,3,4,5]
[2,3,4,5,1]
[3,4,5,1,2]
[4,5,1,2,3]
[5,1,2,3,4]
I am trying with .cycle method of array but it is not giving the expected result.
Check out rotate.
a = [ "a", "b", "c", "d" ]
a.rotate #=> ["b", "c", "d", "a"]
irb(main):005:0> array = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb(main):006:0> array.size.times.map{|i| array.rotate(i)}
=> [[1, 2, 3, 4, 5], [2, 3, 4, 5, 1], [3, 4, 5, 1, 2], [4, 5, 1, 2, 3], [5, 1, 2 , 3, 4]]
Sorry for the messy title.
If I use static values (rails console):
2.1.2 :013 > h=[]
=> []
2.1.2 :014 > h<<[1]
=> [[1]]
2.1.2 :015 > h<<[1,2]
=> [[1], [1, 2]]
2.1.2 :016 > h<<[1,2,3]
=> [[1], [1, 2], [1, 2, 3]]
It works as expected. Same if I use a variable that uses static values, like this:
2.1.2 :018 > h=[]
=> []
2.1.2 :019 > a=1
=> 1
2.1.2 :020 > h<<a
=> [1]
2.1.2 :021 > a=[1,2]
=> [1, 2]
2.1.2 :022 > h<<a
=> [1, [1, 2]]
2.1.2 :023 > a=[1,2,3]
=> [1, 2, 3]
2.1.2 :024 > h<<a
=> [1, [1, 2], [1, 2, 3]]
But if I do the following, the values of the variable are replaced onto the entire array, like it was a pointer:
2.1.2 :036 > h=[]
=> []
2.1.2 :037 > a=[]
=> []
2.1.2 :038 > a<<1
=> [1]
2.1.2 :039 > h<<a
=> [[1]]
2.1.2 :040 > a<<2
=> [1, 2]
2.1.2 :041 > h<<a
=> [[1, 2], [1, 2]]
2.1.2 :042 > a<<3
=> [1, 2, 3]
2.1.2 :043 > h<<a
=> [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Notice how all the values of h get replaced by the new value of a.The same happens if I use "h.append(X)". If I use another variable, the values don't get replaced:
2.1.2 :044 > b=[1,2,3]
=> [1, 2, 3]
2.1.2 :045 > b<<4
=> [1, 2, 3, 4]
2.1.2 :046 > h<<b
=> [[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3, 4]]
I've temporary solved this by using something like "h << a.to_s", but that converts the numerical values to strings, which causes problems when I need to do math with them. Another alternative I ran into is by using "h << a.inspect", except the values get encased by quotes like this:
["[1]", "[1,2]", "[1,2,3]"]
which is ok'ish, but the quotes cause other problems as well. Ideally, I'd want them like this:
[[1], [1,2], [1,2,3]]
Is there a way to prevent this from happening? Or perhaps, using a different way to insert the arrays into a hash/array/json variable?
You can duplicate the reference before inserting into the array:
> h = []
> a = []
> a << 1
> h << a.dup
> a << 2
> h << a.dup
> a << 3
> h << a.dup
> h
# => [[1], [1, 2], [1, 2, 3]]
You need to understand that Ruby effectively passes parameters by reference¹ – only basic types like floats, ints, true, false and nil are immutable and thus will not expose the behaviour you observed. For all other objects, one possible workaround is to use dup:
h = []
a = []
a = a.dup << 1 #=> [1]
h << a #=> [[1]]
a = a.dup << 2 #=> [1, 2]
h << a #=> [[1], [1, 2]]
a = a.dup << 3 #=> [1, 2, 3]
h << a #=> [[1], [1, 2], [1, 2, 3]]
h #=> [[1], [1, 2], [1, 2, 3]]
Another way is to make use of +=, which implicitly returns a copy. However, the right hand argument then must be an array instead of a single value:
h = []
a = []
a += [1] #=> [1]
h << a #=> [[1]]
a += [2] #=> [1, 2]
h << a #=> [[1], [1, 2]]
a += [3] #=> [1, 2, 3]
h << a #=> [[1], [1, 2], [1, 2, 3]]
h #=> [[1], [1, 2], [1, 2, 3]]
¹Although internally, Ruby passes them by value, but these values are references
You can get object id for variable 'a' by Object#object_id, it can help you understand.
irb(main):060:0> a= 1
=> 1
irb(main):061:0> a.object_id
=> 3
irb(main):062:0> a= [1,2]
=> [1, 2]
irb(main):063:0> a.object_id
=> 20017440
irb(main):064:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):065:0> a.object_id
=> 19627820
The object_id of variable a is different.
irb(main):066:0> a= []
=> []
irb(main):067:0> a << 1
=> [1]
irb(main):068:0> a.object_id
=> 18718920
irb(main):069:0> a << 2
=> [1, 2]
irb(main):070:0> a.object_id
=> 18718920
irb(main):071:0> a << 3
=> [1, 2, 3]
irb(main):072:0> a.object_id
=> 18718920
If you use "<<", the object_id of variable 'a' will not change, if you change the value of variable a, all elements of array 'h' will change.
So you can use 'a.dup' get a shallow copy of object a, then add it to array h.
I have an array of arrays like so: [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]. I want to check whether the larger array contains arrays of a given number without regard to the animal element of the array. I also do not want to loop through the array because this would become computationally heavy.
So something like #boolean = bigArray.include?([2, *]), except something that actually works...
You have two possible solutions. Detect the element in the array or convert the array into a Hash
1. Use Enumerable#detect, it will stop as soon as it finds a match and return it, nil otherwise.
> a = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
=> [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
> a.detect{ |(n, _)| n == 2 }
=> [2, "cat"]
> a.detect{ |(n, _)| n == 10 }
=> nil
If you want to add this to the Array class like your example, and force it to return a boolean, do this:
class Array
def custom_include?(num)
!!detect{ |(n, _)| num == n }
end
end
Example:
> a.custom_include?(2)
=> true
> a.custom_include?(10)
=> false
2. If you don't care about the colliding keys, you could convert the array into a Hash and see if the key exists.
> a = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
=> [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
> Hash[a][2]
=> "bird"
> Hash[a][10]
=> nil
One very simple way that doesn't involve looping is to convert the structure to a hash. Your arrays happen to be in an ideal format for this:
values = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
Hash[values][2] # "bird"
You will lose the first value for each key, but it will serve to show whether a key exists.
We can use this:
arr = [[1, "dog"], [2, "cat"], [2, "bird"], [3, "monkey"]]
arr.assoc(2)
it will return [2, cat]
in array if element is not exist
arr.assoc(10)
returns nil
This question already has answers here:
How to determine if one array contains all elements of another array
(8 answers)
Closed 3 years ago.
Is there any method to check if array A contains all the elements of array B?
You can try this
a.sort.uniq == b.sort.uniq
or
(a-b).empty?
And if [1,2,2] != [1,2] in your case you can:
a.group_by{|i| i} == b.group_by{|i| i}
This should work for what you need:
(a & b) == b
You could use Ruby's Set class:
>> require 'set' #=> true
>> a = [*1..5] #=> [1, 2, 3, 4, 5]
>> b = [*1..3] #=> [1, 2, 3]
>> a.to_set.superset? b.to_set #=> true
For small arrays I usually do the same as what fl00r suggested:
>> (b-a).empty? #=> true
I prefer to do this via: (b - a).blank? # tells that b is contained in a
The simplest way is this:
(b-a).empty?
There's also the Set class (part of the standard library) which would allow you to just check to see if B is a subset of A, e.g.
>> a = [1,2,3,4,5] => [1, 2, 3, 4, 5]
>> b = [3,4,5] => [3, 4, 5]
>> require 'set' => true
>> set_a = a.to_set => #<Set: {1, 2, 3, 4, 5}>
>> set_b = b.to_set => #<Set: {3, 4, 5}>
>> set_b.subset? set_a => true
http://www.ruby-doc.org/stdlib/libdoc/set/rdoc/index.html
Ruby 2.6+
Ruby's introduced difference in 2.6 for exactly this purpose.
Very fast, very readable, as follows:
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3, 4, 5, 6]
a.difference(b).any?
# => false
a.difference(b.reverse).any?
# => false
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3]
a.difference(b).any?
# => true
Hope that helps someone!
You may want to check out the Set class in the Ruby Standard library. The proper_subset? method will probably do what you want.