How to remove dups from 2 lists?

On 5/11/07, Lloyd L. [email protected] wrote:

  1. don’t go so far as remove more than the common count of dups

a = a - c
[1, 3]
[6, 8]


Posted via http://www.ruby-forum.com/.

What happens here? :slight_smile:
All 5’s are deleted.
I don’t know if that is what he wants but I interpreted it differently.

a = [1, 2, 3, 4, 5, 5, 5]
b = [2, 4, 6, 8, 5]

p a
p b

c = a & b
a = a - c
b = b - c

p c
p a
p b

Harry

On 5/12/07, Lloyd L. [email protected] wrote:

Anyway, this is my first attempt at writing code to solve a question in
here. I am happy that I was able to come up with something that worked
and post it. :slight_smile:

yay ruby!

Yeah, this is very educational.
I learn from reading posts from others and by trying to solve problems
that other people have.

It’s like a lot of mini Ruby Q.zes.

Harry

On 5/11/07, Mike S. [email protected] wrote:

I’m looking for a function that will eliminate all matching items, like
canceling terms in a fraction. If the first list has 3 "a"s, and the second
list has 5 "a"s, then afterwards the first list should have 0 "a"s and the
second list should have 2 "a"s.

I thought this looked a lot like simplification. I can find a lot of
uses for this simple function.

I’m looking for a function that will eliminate all matching items, like
canceling terms in a fraction. If the first list has 3 "a"s, and the
second
list has 5 "a"s, then afterwards the first list should have 0 "a"s and
the
second list should have 2 "a"s.

Mike S.

Looks good to me!

each_item should read each_index
and (perhaps) remove nil check and we’re off.

   list2.each_index do | j |

difficult in Ruby. Everything else I’ve seen has been MUCH easier in
Ruby.

Mike S.

Isn’t this what you want?

irb(main):001:0> a = %w{a b c d e f g a b c}
=> [“a”, “b”, “c”, “d”, “e”, “f”, “g”, “a”, “b”, “c”]
irb(main):002:0> b = %w{e f g h i j k h i j}
=> [“e”, “f”, “g”, “h”, “i”, “j”, “k”, “h”, “i”, “j”]
irb(main):003:0> a - (a & b)
=> [“a”, “b”, “c”, “d”, “a”, “b”, “c”]
irb(main):004:0> b - (a & b)
=> [“h”, “i”, “j”, “k”, “h”, “i”, “j”]

Wolfgang Nádasi-Donner

Good idea about the & operator for sets, but there could be more than 1
group of matches, so I’d have to iterate:

a = [ 1, 1, 2, 3, 4, 4, 4, 5 ]
b = [ 1, 2, 2, 4, 4, 6, 7 ]
results = a & b
while results
results.each do | m |
a = a - m
b = b - m
end
results = a & b
end

I think this will work, and it’s sort of elegant (well, not as elegant
as
having it built into Ruby already :-)).

Mike S.

   list2.each_index do | j |

difficult in Ruby. Everything else I’ve seen has been MUCH easier in
Ruby.

Mike S.

Or is it something like this?

Here only common elements of both lists are deleted from left to right,
but if a
list contains more elements, e.g. “a” than the other, only the number of
"a"s
that are in the other list will be deleted from the one, which has more
"a"s (I
don’t know how to describe it - the code should explain ist):

a = %w{a b a a c a b c d e f e a}
b = %w{a b a c d c d c c g h g c}
puts ‘— before —’
p a
p b
ah = a.inject(Hash.new(0)){|h,w|h[w]+=1;h}
bh = b.inject(Hash.new(0)){|h,w|h[w]+=1;h}
abh = (ah.keys & bh.keys).inject({}){|h,w|h[w]=[ah[w], bh[w]].min;h}
[a, b].each{|arr|abh.each{|k,v|v.times{arr.delete_at(arr.index(k)) if
arr.include?(k)}}}
puts ‘— after —’
p a
p b

Output:

— before —
[“a”, “b”, “a”, “a”, “c”, “a”, “b”, “c”, “d”, “e”, “f”, “e”, “a”]
[“a”, “b”, “a”, “c”, “d”, “c”, “d”, “c”, “c”, “g”, “h”, “g”, “c”]
— after —
[“a”, “a”, “b”, “e”, “f”, “e”, “a”]
[“d”, “c”, “c”, “g”, “h”, “g”, “c”]

Wolfgang Nádasi-Donner

Wolfgang Nádasi-Donner schrieb:

Or is it something like this?


— before —
[“a”, “b”, “a”, “a”, “c”, “a”, “b”, “c”, “d”, “e”, “f”, “e”, “a”]
[“a”, “b”, “a”, “c”, “d”, “c”, “d”, “c”, “c”, “g”, “h”, “g”, “c”]
— after —
[“a”, “a”, “b”, “e”, “f”, “e”, “a”]
[“d”, “c”, “c”, “g”, “h”, “g”, “c”]

If it is the wanted direction, the program is simple.

class Array
def remdups(b)
a= self.dup
b.each{|el|a.delete_at(a.index(el)) if a.include?(el)}
a
end
end

a = %w{a b a a c a b c d e f e a}
b = %w{a b a c d c d c c g h g c}
puts ‘— before —’
p a
p b
puts ‘— after —’
p a.remdups(b)
p b.remdups(a)
p [1,1,1,1].remdups([1,1,2])
p [1,1,2].remdups([1,1,1,1])

Output:

— before —
[“a”, “b”, “a”, “a”, “c”, “a”, “b”, “c”, “d”, “e”, “f”, “e”, “a”]
[“a”, “b”, “a”, “c”, “d”, “c”, “d”, “c”, “c”, “g”, “h”, “g”, “c”]
— after —
[“a”, “a”, “b”, “e”, “f”, “e”, “a”]
[“d”, “c”, “c”, “g”, “h”, “g”, “c”]
[1, 1]
[2]

Wolfgang Nádasi-Donner

Wolfgang, that is VERY slick! Well done!

Mike S. wrote:

while results

Well, this while loop will not terminate because [] is considered true
in ruby, use this instead

while results != []

or the more idiomatic

while not results.empty?

    a = a - m
    b = b - m

I don’t think that this ‘-’ works here, you probably meant:

a.delete_at(a.index(m))
b.delete_at(b.index(m))

because a = a - [m] will remove all m’s of a and make the code do the
same as:

a, b = a - (a&b), b - (a&b)

although i like the elegance of that solution i prefer something like
this:

def removeDupsFromLists ( list1 , list2 )
x = list1.dup
x.each do | i |
if list2.include?(i)
list1.delete_at( list1.index(i) )
list2.delete_at( list2.index(i) )
end
end
return [ list1, list2 ]
end

just because is easier to follow and to debug: there is no way of get an
infinte loop

MoisesMachado

Lloyd L. wrote:

I am new to Ruby but I am wondering why it is that no one is using the
uniq call that gets rid of duplicates in an array.

Using uniq would get rid of the duplicates in each list. The original
question specified that duplicates within a list are not to be removed.

However, I don’t want any duplicates from each list deleted

Ray

On 5/11/07, Wolfgang Nádasi-Donner [email protected] wrote:

If it is the wanted direction, the program is simple.

class Array
def remdups(b)
a= self.dup
b.each{|el|a.delete_at(a.index(el)) if a.include?(el)}
a
end
end

Or somewhat faster, particularly for long arrays:

class Array

def rem_dups(b)
a = dup
b.each { | e | i = a.index(e); a.delete_at(i) if i}
a
end
end

Which avoids scanning the array twice for each element.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/