Tengo una serie de números flotantes y un cierto límite:

myData = [1.3,1.5,1.7,1.7,16.7,18.4,19.2,19.5,19.6,20.2,20.8,58.4,60.7,
          61.2,61.2,116.4,121.2,122.7,123.2,123.2,138.5,149.5,149.5]
myBin = 5.3

Me gustaría construir un hash de matrices para que la diferencia por sustracción entre el último elemento y el primer elemento de la matriz sea menor o igual que myBin (5.3)

myHash = {
'hap_1' => [1.3,1.5,1.7],
'hap_2' => [16.8, 18.4,19.2,19.5,19.6,20.2,20.8],
'hap_3' => [58.4,60.7,61.2,61.2],
'hap_4' => [116.4,121.2],
'hap_5' => [122.7,123.2,123.2],
'hap_6' => [138.5],
'hap_7' => [149.5,149.5]}

Muchas gracias de antemano por su tiempo y ayuda útil. Salud

0
Kpangee 26 oct. 2017 a las 20:47

3 respuestas

La mejor respuesta
myData.drop(1).each_with_object([[myData.first]]) { |n,a|
  n - a.last.first <= myBin ? (a.last << n) : a << [n] }.
  each.with_index(1).with_object({}) { |(a,i),h| h["hap_#{i}"] = a }
  #=> {"hap_1"=>[1.3, 1.5, 1.7, 1.7],
  #    "hap_2"=>[16.7, 18.4, 19.2, 19.5, 19.6, 20.2, 20.8],
  #    "hap_3"=>[58.4, 60.7, 61.2, 61.2],
  #    "hap_4"=>[116.4, 121.2],
  #    "hap_5"=>[122.7, 123.2, 123.2],
  #    "hap_6"=>[138.5],
  #    "hap_7"=>[149.5, 149.5]}
1
Cary Swoveland 26 oct. 2017 a las 19:39

Enumerable#slice_before puede resolver su problema :

first = myData[0]
myData.slice_before { |e| first = e if e - first > myBin }.to_a
#=> [[1.3, 1.5, 1.7, 1.7],
#    [16.7, 18.4, 19.2, 19.5, 19.6, 20.2, 20.8],
#    [58.4, 60.7, 61.2, 61.2],
#    [116.4, 121.2],
#    [122.7, 123.2, 123.2],
#    [138.5],
#    [149.5, 149.5]]
6
Ilya 26 oct. 2017 a las 18:16

Podría crear un enumerador de clientes que funcione como chunk_while, pero compare el elemento first de cada fragmento con el elemento actual, es decir, 1.3 con 1.5, luego {{X3 }} a 1.7 y así sucesivamente:

module Enumerable
  def chunk_while1
    return enum_for(__method__) unless block_given?
    each_with_object([]) do |elt, result|
      if result.last && yield(result.last.first, elt)
        result.last << elt
      else
        result << [elt]
      end
    end
  end
end

Uso:

data = [
  1.3, 1.5, 1.7, 1.7, 16.7, 18.4, 19.2, 19.5, 19.6, 20.2, 20.8, 58.4, 60.7,
  61.2, 61.2, 116.4, 121.2, 122.7, 123.2, 123.2, 138.5, 149.5, 149.5
]

result = data.chunk_while1 { |i, j| j - i <= 5.3 }
#=> [
#     [1.3, 1.5, 1.7, 1.7],
#     [16.7, 18.4, 19.2, 19.5, 19.6, 20.2, 20.8],
#     [58.4, 60.7, 61.2, 61.2],
#     [116.4, 121.2],
#     [122.7, 123.2, 123.2],
#     [138.5],
#     [149.5, 149.5]
#   ]

El resultado se puede convertir a un hash, p. vía:

result.map.with_index(1) { |a, i| ["hap_#{i}", a] }.to_h
#=> {
#     "hap_1"=>[1.3, 1.5, 1.7, 1.7],
#     "hap_2"=>[16.7, 18.4, 19.2, 19.5, 19.6, 20.2, 20.8],
#     "hap_3"=>[58.4, 60.7, 61.2, 61.2],
#     "hap_4"=>[116.4, 121.2],
#     "hap_5"=>[122.7, 123.2, 123.2],
#     "hap_6"=>[138.5],
#     "hap_7"=>[149.5, 149.5]
#   }
0
Stefan 27 oct. 2017 a las 09:02