¿Cómo puedo obtener la intersección, unión y subconjunto de matrices en Ruby?

170

Quiero crear diferentes métodos para una clase llamada Multiset .

Tengo todos los métodos requeridos, pero no estoy seguro de cómo escribir los métodos de intersección, unión y subconjunto.

Para intersección y unión, mi código comienza así:

def intersect(var)
  x = Multiset.new
end

Aquí hay un ejemplo:

X = [1, 1, 2, 4]
Y = [1, 2, 2, 2]

entonces la intersección de Xy Yes [1, 2].

usuario487743
fuente
El enlace de @ Krule está roto, pero creo que te estaba señalando el método "&" de Array que hace intersección, mira algunas de las respuestas aquí.
rogerdpack
Eso fue respondido hace más de 8 años. Sí, eso fue intersección, ruby-doc.org/core-2.6.3/Array.html#method-i-26
Krule

Respuestas:

151

Aprovechando el hecho de que puede establecer operaciones en matrices haciendo &(intersección), -(diferencia) y |(unión).

Obviamente no implementé el MultiSet para especificar, pero esto debería ayudarlo a comenzar:

class MultiSet
  attr_accessor :set
  def initialize(set)
    @set = set
  end
  # intersection
  def &(other)
    @set & other.set
  end
  # difference
  def -(other)
    @set - other.set
  end
  # union
  def |(other)
    @set | other.set
  end
end

x = MultiSet.new([1,1,2,2,3,4,5,6])
y = MultiSet.new([1,3,5,6])

p x - y # [2,2,4]
p x & y # [1,3,5,6]
p x | y # [1,2,3,4,5,6]
Mike Lewis
fuente
8
2 grandes crímenes en esta respuesta: (1) La palabra setcomo nombre variable de una matriz simple; (2) Replicando todo lo que Arrayya hace. Si el OP quiere agregar funcionalidad a la Arrayclase con algunos métodos adicionales, simplemente debe hacer: class MultiSet < Array def inclusion?(other) Set.new(self).subset?(Set.new(other)) end end
Rahul Murmuria
1
De acuerdo ... esta es probablemente la clase más inútil que he visto en mi vida ... pero me doy cuenta de que no es realmente tu culpa.
Desarrollado el
313

Supongo Xy Yson matrices? Si es así, hay una manera muy simple de hacer esto:

x = [1, 1, 2, 4]
y = [1, 2, 2, 2]

# intersection
x & y            # => [1, 2]

# union
x | y            # => [1, 2, 4]

# difference
x - y            # => [4]

Fuente

Jon Gauthier
fuente
17
En otras palabras, solo hazlo Multiset < Array.
sawa
¿Qué pasa si tienes x = [1,1,2,4] y = [1,2,2,2] z = [4] ¿Cómo puedes conseguir que te dé intersecciones entre conjuntos en lugar de la intersección de todos conjuntos? Entonces, en lugar de darte [], ¿te da [1,2,4]?
mharris7190
1
@ mharris7190 se puede tomar la unión de todas esas intersecciones:(x & y) | (y & z) | (x & z)
xavdid
2
No se olvide también existe &=, |=y -=si también desea almacenar el valor de inmediato como lo hice! :)
Pysis
2
Exactamente lo que pensaba @sawa. ¿Por qué el OP está creando esta clase en primer lugar? No hace nada que Array no haga desde Ruby's Standard Lib.
danielricecodes
6

Si se Multisetextiende desde la Arrayclase

x = [1, 1, 2, 4, 7]
y = [1, 2, 2, 2]
z = [1, 1, 3, 7]

UNIÓN

x.union(y)           # => [1, 2, 4, 7]      (ONLY IN RUBY 2.6)
x.union(y, z)        # => [1, 2, 4, 7, 3]   (ONLY IN RUBY 2.6)
x | y                # => [1, 2, 4, 7]

DIFERENCIA

x.difference(y)      # => [4, 7] (ONLY IN RUBY 2.6)
x.difference(y, z)   # => [4] (ONLY IN RUBY 2.6)
x - y                # => [4, 7]

INTERSECCIÓN

x & y                # => [1, 2]

Para obtener más información sobre los nuevos métodos en Ruby 2.6, puede consultar esta publicación de blog sobre sus nuevas características

Ana María Martínez Gómez
fuente