looping through nested arrays and accessing elements RUBY - arrays

I want to iterate through a nested array and operate on each element, so square each number in this case. I know how to do it for a normal array but for some reason i am getting undefined map method when include deeper iteration to access the inner arrays. Am a newbie too so if you could explain how it works that would help my learning. Thanks
def SquareArrayElements(n)
n.each do |number|
number.map do |num|
squared_nums = num * num
end
end
squared_nums
end
SquareArrayElements([10,[[10],10],[10]])

Since you've said in the comments that:
i want to square the 10s and return them to one array =>[100,100,100,100].
I assume that you don't need to preserve the original arrays and just want one array with the squared results. If that's the case you can #flatten the array and then square the numbers:
def square_array(arr)
arr.flatten.map { |e| e ** 2 }
end
square_array([10,[[10],10],[10]])
#=> [100, 100, 100, 100]

You only need to call map on the arrays, not on the integers. That's why you're getting an undefined map method, integers don't support that method.
Try
def square_array(element)
if element.responds_to?(:map)
element.map{|m| square_array(m)}
else
element * element
end
end

Related

Count the number of elements of array that contain a digit

i am new to Ruby and stuck on this exercice. I have this array including string value and i am looking for the number of value including a figure ?
array = ["#jcunniet","#PaulLampon","#Aziliz31","#ssoumier","#marionsouzeau","#gaellombart","#bendarag","#AurelieLebelle","#julienduffe","#thomaspoupeau","#LilyRossignol","#ClairGuedon","#stephanieauguy","#claw_prolongeau","#_JulieMenard","#LColcomb","#Zlauwereys","#MeLonguet","#DorotheeLN","#NolwennCosson","#ADaboval","#Remibaldy","#bderveaux","#amandechap","#ELODIESOULIE","#nbongarcon","#HeloAb","#Panamorama","#gregplou","#BenoitBerthe","#LauraBruneau89","#Anthony_Lieures","#Sharonwaj","#mcsonkin","#pverduzier","#emiliel3","#Julien_MARION","#SophiFay","#bdelombre","#annalecerf","#AdriaBudry","#DejNikolic","#iJaffre","#CyrusleVirus","#GPardigon","#e_vallerey","#IsabelleSouquet","#AudeDavidRossi","#Yoann_Pa","#CeliaPenavaire","#perraultvincent","#cboulate","#JustineWeyl","#Paulinejacot","#juliechab","#aslechevallier","#phnou","#Seb_Pommier","#Alex_Bensaid","#GuillaumeGaven","#annelaurechouin","#Oliviader","#guerricp","#JMMarchaut","#cyceron","#gregory_raymond","#vhunsinger","#l_peillon","#fannyguinochet","#EAssayag","#KibweAdom","#YvonHerry","#JohanGarciajg","#saidlabidi","#lauranneprov","#LeaDavy","#francois_remy","#CGuicheteau","#FloMaillet","#m_perroud","#oBrunet_TSMF","#MoonVdc","#jc2taille","#NellyMoussu","#VirginK","#b_misa","#FabriceCouste","#barbara_prose","#lelia2m","#brunoaskenazi","#laurenechamp","#ysisbox","#juliengagliardi","#PierreLel","#kdeniau","#_TerraInc","#DominicArpin","#antoinfonteneau","#nanotousch","#jb_roch","#YaniKhezzar","#Anne_Bechet","#NCapart","#SamyBenNaceur","#Joumany","#Julietteraynal","#TGiraudet","#SaraTanit","#HappeFrederic","#antoinellorca","#michelpicot","#Sev_Ryne","#bobdobolino","#murdever","#YGrandmontagne","#Mnyo","#EdKOSCIANSKI","#tnoisette","#jankari","#delbello_rom","#rflechaux","#NadiaSorelli","#IT_Digital","#abarbaux","#PhilippeLeroy","#schaptal","#marionspee","#lisavignoli","#ChloeAeberhardt","#MartineJacot","#JuliaPascualita","#curieusedetout","#sgraveleau","#bif_o","#ElisaPineau","#zinebdryef","#apiquard","#pierrehaski","#StephanieDelmas","#Blandine_Garot","#vergara_i","#evan_lebastard","#SophieVclt","#OlivierLevrault","#alicedorgeval","#LouiseMalnoy","#alix_fx","#pierre_baudis","#LucMagoutier","#AgatheMuller","#SGianninelli","#PaulineBoyer33","#NaomiHalll","#romaindlx","#marionbr","#Burtschy","#JacobEtienne","#as_lizzani","#marie_simon","#LaureDaussy","#FabriceAmedeo","#LoubnaChlaikhy","#PlummerWilliam","#OlivierMarin1","#alaurefremont","#mwesfreid","#ChBaDe","#pmathon","#theobaldmarie","#Lnpagesy","#marclandre","#paoliniesther","#Feertchak","#JBLitzler","#GuillaumeErrard","#quentinperinel","#TristanQM","#mlbo","#constancejamet","#LoraTerrazas","#emiliegeffray","#Mathilde_Sd","#CaroPiquet","#DCanivez","#TIM_7375","#blandinelc","#ivanrioufol","#arthurberdah","#SarahLecoeuvre","#guillaume_gui","#DamienMercereau","#W_Chloe","#Assma_MD","#EugenieBastie","#HiTech_lexpress","#bcondominas","#Laurie_Z_","#jeanfrancgerard","#MathieuPagura","#BGUYF","#AlainPiffaretti","#AudreyKucinskas","#julienhory","#Pierrefalga","#TiphThuillier","#cdaniez","#LigerBaptiste","#D_Peras","#julie_dlb","#Fatiha_Temmouri","#julian2lamancha","#GaetaneDeljurie","#JulianMattei","#M_Vicuna","#DeBruynOlivier","#Nehed_Jendoubi","#antoine_grenapi","#ColonnaGen","#VictoriaGairin","#Clement_Lacombe","#TVigoureux","#MargauxObriot","#solinedelos","#RocheSabine","#dangerkens","#EdouardDutour","#MDondeyne","#DupuisNathalie1","#bouscarel","#Mathieu2jean","#Sophie_T_J","#laurentcalixte","#patrockwilliams","#PascaleKremer","#AlexJaquin","#LauraIsaaz","#cath_robin","#Del_Gautherin","#Isaduriez","#lucietuile","#AugeyBastien","#mcastagnet","#AminaKalache","#mvaudano","#CParrot","#ombelinetips","#_JoinLion","#BarbolosiRose","#ToiBruno1","#FloraClodic","#xjbdx","#AlexiaEy","#Emjy_STARK","#elcoco01","#rabilebon","#pflovens_","#FabriceFrossard","#MorganeSERRES","#MarjolaineKoch","#edgarsnow","#SRNLF","#CChassigneux","#KerinecMoran","#NassiraELM","#NewsRicard","#Sandreene","#Emilezrt","#Pierre_Do","#Micode","#CColumelli","#DavidAbiker","#ClementBergantz","#benjaminrabier","#celinekallmann","#edwyplenel","#C_Barbier","#JJBourdin_RMC","#LaurenceFerrari","#aslapix","#IsaMillet","#MaximeSwitek","#tomjoubert","#jszanchi","#roqueeva","#XavierBiseul","#florencesantrot","#AntoineCrochet","#freeman59","#MaudeML","#philippe_gulpi","#mathieum76","#kiouari","#imanemoustakir","#BenedicteMallet","#Emilie_Brouze","#antoinebarret","#_nicolasbocquet","#remibuhagiar","#CourretB","#AymericRobert","#miraelmartins","#pmaniere","#jesuisraphk","#David_Ingram","#pcelerier","#technomedia","#Geraldinedauver","#ThierryLabro","#Newsdusud","#nrauline","#gbregeras","#SCouasnonBFM","#actualites_nrv","#dimitrimoulins","#oli_aura","#FabieChiche","#Vincent_Raimblt","#ChristophGreuet","#PAlbuchay","#MarrauddesGrot","#vtalmon","#cedric","#olivierfrigara","#Julien_Jay","#LydiaBerroyer","#Shuua","#datisdaz","#Steuph","#ameliecharnay","#Bruno_LesNums","#LelloucheNico","#CciliaDiQuinzio","#Elodie_C","#SylvRolland","#Kocobe","#FL_Debes","#jdupontcalbo","#GarciaVictor_","#NicoRichaud","#RHoueix","#simottel","#DamienLicata","#annabelle_L","#Lea_Lejeune","#axel_deb","#marin_eben","#ptiberry","#MatthieuDelach","#sandrinecassini","#benjaminferran","#ppgarcia75","#NotPatrick","#ivalerio","#FabienneSchmitt","#alexgoude","#JeromeColombain","#manhack","#Capucine_Cousin","#Fsorel","#oliviertesquet","#marjoriepaillon","#ginades","#PierreTran","#DelphineCuny","#reesmarc","#lauratenoudji","#ldupin","#carolinedescham","#Lucile_Quillet","#cgabizon","#Allocab","#epenser","#JAGventeprivee","#frwrds","#Laure__Bourdon","#Xavier75","#maximeverner","#s_jourdain","#LoriHelloc"]
i = 0
array.each do |n|
if n.include?("1,2,3,4,5,6,7,8,9,10")
then i += 1
end
puts i
end
Do you mean something like this?
array.grep(/[1-9]/).count
Edit: Changed regEx from /[1-10]/ to /[1-9]/
Often code that is the direct translation of the question is best: “Count the number of elements of array that contain a digit”.
array.count { |s| s.match? /\d/ }
See Array#count and String#match?.

Ruby method to sum all values in a multidimensional array

I am trying to sum the elements of an array. WITHOUT using flatten. I have tried using the following:
def multi_array_sum(arr)
sum = 0
arr.each do |row|
row.each do |column|
sum += column
end
end
return sum
end
but unfortunately, it is not working. I am not sure how to iterate though a multidimensional array considering that I cannot use each if the first element in the array is not another array itself, for example, array = [[1, [1, 2], [3, 4, 5]].
If all elements are numeric or arrays, and you want to sum them all:
array.flatten.inject(:+)
Just use standard array functions and then enumerable.
array.flatten.reduce(:+)
If you are 100% sure that you cannot use flatten then you can use:
array.map { |a| a.reduce(:+) }.reduce(:+)
So if you absolutely can't use flatten (which is a bit weird), you can use a simple recursive method:
def multi_array_sum(arr)
case arr
when Fixnum
arr
when Array
arr.reduce(0) { |agg, sub_arr| agg + multi_array_sum(sub_arr) }
end
end
If each inner array is the same size and contains only numbers, you could use the method Matrix#[] to convert the array to a matrix, Matrix#each (without a block) to create an enumerator to generate the elements of the matrix, and Enumerable#reduce (aka inject) to compute the sum of all elements of the matrix.
require 'matrix'
def sum_all(arr)
Matrix[*arr].each.reduce(:+)
end
sum_all [[1,2],[3,4]] #=> 10

Intersection of an arbitrary number of arrays

I need a function which takes an array of arrays as its argument, then returns the intersection of all the subarrays. How could I improve the following code, if at all?
class Array
def grand_intersection
if self.length > 1
filters = self[1..-1]
filters.reduce(self[0]) {|start, filter| start & filter}
else
self
end
end
end
P.S. I'm not too concerned about handling arrays whose content won't respond to #& -- the method won't be exposed to the user.
class Array
def grand_intersection
self.reduce :&
end
end
[[1,2,3,4,5], [2,3,4], [1,2,4,5]].grand_intersection
#=> [2, 4]

Ruby Iterating through multidimensional arrays

I just wanna know if there are other good ways to solve problems like the following:
p [1,[2,3,"hi",[[[[2,"ex","bye"]]]]]].count_type(String)
# => 3
So our goal is to count the types in a multidimensional Array but, as i said, problems like this, not just this problem. The general problem is that we get multidimensional Arrays and then we need to search for types or Arrays which have a minimum index of 2 or some other conditions. I am sorry for my bad language usage and hope you get the point.
I know that recursive methods work. But is there any other way with recursive or non recursive implementation?
I use the following:
def count_type(type)
counter = 0
self.each { |elem|
if elem.is_a?(type)
counter +=1
end
if elem.is_a?(Array)
counter += elem.method(type)
end
}
end
return counter
I know that the part with elem.is_a?(type) differs and depends on what you are asking for.
I forgot to tell you that it is forbidden to use flatten and my goal is not adding a new method to class Array but to learn new ways to solve the above explained problems.
I'd try and make this more in line stylistically with the Ruby core functions especially if you're intending to add it to Array:
class Array
def deep_count(*args, &block)
count = self.count(*args, &block)
each do |e|
count += e.deep_count(*args, &block) if e.is_a?(Array)
end
count
end
end
[1,[2,3,"hi",[[[[2,"ex","bye"]]]]]].deep_count {|v| v.is_a?(String)}
# => 3
[1,[2,3,"hi",[[[[2,"ex","bye"]]]]]].deep_count(2)
# => 2
Update: Version without patching core Array:
def array_deep_count(array, *args, &block)
count = array.count(*args, &block)
array.each do |e|
count += e.deep_count(*args, &block) if e.is_a?(Array)
end
count
end
This largely involves swapping self with an argument.

Getting the first and last element of an array in CoffeeScript

If say I have an array and I would to iterate through the array, but do something different to the first and last element. How should I do that?
Taking the below code as example, how do I alert element a and e?
array = [a,b,c,d,e]
for element in array
console.log(element)
Thanks.
You can retrieve the first and last elements by using array destructuring with a splat:
[first, ..., last] = array
This splat usage is supported in CoffeeScript >= 1.7.0.
The vanilla way of accessing the first and last element of an array is the same as in JS really: using the index 0 and length - 1:
console.log array[0], array[array.length - 1]
CoffeeScript lets you write some nice array destructuring expressions:
[first, mid..., last] = array
console.log first, last
But i don't think it's worth it if you're not going to use the middle elements.
Underscore.js has some helper first and last methods that can make this more English-like (i don't want to use the phrase "self-explanatory" as i think any programmer would understand array indexing). They are easy to add to the Array objects if you don't want to use Underscore and you don't mind polluting the global namespace (this is what other libraries, like Sugar.js, do):
Array::first ?= (n) ->
if n? then #[0...(Math.max 0, n)] else #[0]
Array::last ?= (n) ->
if n? then #[(Math.max #length - n, 0)...] else #[#length - 1]
console.log array.first(), array.last()
Update
This functions also allow you to get the n first or last elements in an array. If you don't need that functionality then the implementation would be much simpler (just the else branch basically).
Update 2
CoffeeScript >= 1.7 lets you write:
[first, ..., last] = array
without generating an unnecessary array with the middle elements :D
The shortest way is here
array[-1..]
See this thread
https://github.com/jashkenas/coffee-script/issues/156
You can use just:
[..., last] = array
You can use slice to get last element. In javascript, slice can pass negative number like -1 as arguments.
For example:
array = [1, 2, 3 ]
console.log "first: #{array[0]}"
console.log "last: #{array[-1..][0]}"
be compiled into
var array;
array = [1, 2, 3];
console.log("first: " + array[0]);
console.log("last: " + array.slice(-1)[0]);
You can get the element and the index of the current element when iterating through the array using Coffeescript's for...in. See the following code, replace the special_process_for_element and normal_process_for_element with your code.
array = [a, b, c, d]
FIRST_INDEX = 0
LAST_INDEX = array.length - 1
for element, index in array
switch index
when FIRST_INDEX, LAST_INDEX
special_process_for_element
else
normal_process_for_element
sample
Here's a working code

Resources