How to remove dups from 2 lists?

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.

···

On 5/11/07, Wolfgang Nádasi-Donner <wonado@donnerweb.de> wrote:

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

--
Rick DeNatale

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

Actually not :wink: It depends if other objects are trying to access those lists at the same time though...

···

On 11 May 2007, at 10:23, Brian Candler wrote:

On Fri, May 11, 2007 at 04:55:14PM +0900, Enrique Comba > Riepenhausen wrote:

Do you want to remove the elements that are in the same position on
the lists and are equal?

If so I would say:

require 'generator'

list1 = [1,1,2,3,4,6] # => I included the 6 to show what I mean...
list2 = [2,2,3,5,5,6] # => I included the 6 to show what I mean...

def RemoveDupsFromLists ( list1 , list2 )
  lists = SyncEnumerator.new(list1, list2)
  lists.each { |element_list1, element_list2|

    if list1[element_list1] == list2[element_list2]
      list1.delete(element_list1)
      list2.delete(element_list2)
    end
  }
end

Is it safe to delete from lists while you're enumerating through them?

Assuming my previous assumption of what exactly is needed... at this point
it's academic anyway, right :>

This will produce the same result with much cleaner code than my previous
post:

APPENDAGE_START = "_"

def make_items_unique(list)
  hsh = Hash.new { |h,k| h[k] = 0}
  list_mod = list.collect do |x|
    hsh += 1
    x.to_s + APPENDAGE_START + hsh.to_s
  end
end

list1 = %w{one one two three four four five}
list2 = %w{one three three four five five five}

puts "before --- list1:#{list1}"
puts "before --- list2:#{list2}"

list1_mod = make_items_unique(list1)
list2_mod = make_items_unique(list2)

list3 = list1_mod - list2_mod
list4 = list2_mod - list1_mod

list1 = list3.collect { |x| x.split(APPENDAGE_START)[0] }
list2 = list4.collect { |x| x.split(APPENDAGE_START)[0] }

puts "after --- list1:#{list1}"
puts "after --- list2:#{list2}"

···

---------------
output=
before --- list1:oneonetwothreefourfourfive
before --- list2:onethreethreefourfivefivefive
after --- list1:onetwofour
after --- list2:threefivefive

On 5/11/07, Enrique Comba Riepenhausen <ecomba@mac.com> wrote:

On 11 May 2007, at 10:23, Brian Candler wrote:

> On Fri, May 11, 2007 at 04:55:14PM +0900, Enrique Comba > > Riepenhausen wrote:
>> Do you want to remove the elements that are in the same position on
>> the lists and are equal?
>>
>> If so I would say:
>>
>> require 'generator'
>>
>> list1 = [1,1,2,3,4,6] # => I included the 6 to show what I mean...
>> list2 = [2,2,3,5,5,6] # => I included the 6 to show what I mean...
>>
>> def RemoveDupsFromLists ( list1 , list2 )
>> lists = SyncEnumerator.new(list1, list2)
>> lists.each { |element_list1, element_list2|
>>
>> if list1[element_list1] == list2[element_list2]
>> list1.delete(element_list1)
>> list2.delete(element_list2)
>> end
>> }
>> end
>
> Is it safe to delete from lists while you're enumerating through them?

Actually not :wink: It depends if other objects are trying to access
those lists at the same time though...

I envision using sets:

a = [a, b, c, d, e, e]
b = [d, e, f, f, g]
dups = a.to_set & b

a -= dups # => [a, b, c]
b -= dups # => [f, f, g]

Or how about just using #-?

a = [a, b, c, d, e, e]
b = [d, e, f, f, g]
c = a.dup
d = b.dup

b -= c # => [a, b, c]
a -= d # => [f, f, g]

Do these fit?

Aur

P.S. have you had a look at http://RubyMentor.rubyforge.org/

···

On 5/11/07, Kevin Compton <klcompt@gmail.com> wrote:

Assuming my previous assumption of what exactly is needed... at this point
it's academic anyway, right :>

This will produce the same result with much cleaner code than my previous
post:

APPENDAGE_START = "_"

def make_items_unique(list)
  hsh = Hash.new { |h,k| h[k] = 0}
  list_mod = list.collect do |x|
    hsh += 1
    x.to_s + APPENDAGE_START + hsh.to_s
  end
end

list1 = %w{one one two three four four five}
list2 = %w{one three three four five five five}

puts "before --- list1:#{list1}"
puts "before --- list2:#{list2}"

list1_mod = make_items_unique(list1)
list2_mod = make_items_unique(list2)

list3 = list1_mod - list2_mod
list4 = list2_mod - list1_mod

list1 = list3.collect { |x| x.split(APPENDAGE_START)[0] }
list2 = list4.collect { |x| x.split(APPENDAGE_START)[0] }

puts "after --- list1:#{list1}"
puts "after --- list2:#{list2}"

---------------
output=
before --- list1:oneonetwothreefourfourfive
before --- list2:onethreethreefourfivefivefive
after --- list1:onetwofour
after --- list2:threefivefive

On 5/11/07, Enrique Comba Riepenhausen <ecomba@mac.com> wrote:
>
> On 11 May 2007, at 10:23, Brian Candler wrote:
>
> > On Fri, May 11, 2007 at 04:55:14PM +0900, Enrique Comba > > > Riepenhausen wrote:
> >> Do you want to remove the elements that are in the same position on
> >> the lists and are equal?
> >>
> >> If so I would say:
> >>
> >> require 'generator'
> >>
> >> list1 = [1,1,2,3,4,6] # => I included the 6 to show what I mean...
> >> list2 = [2,2,3,5,5,6] # => I included the 6 to show what I mean...
> >>
> >> def RemoveDupsFromLists ( list1 , list2 )
> >> lists = SyncEnumerator.new(list1, list2)
> >> lists.each { |element_list1, element_list2|
> >>
> >> if list1[element_list1] == list2[element_list2]
> >> list1.delete(element_list1)
> >> list2.delete(element_list2)
> >> end
> >> }
> >> end
> >
> > Is it safe to delete from lists while you're enumerating through them?
>
> Actually not :wink: It depends if other objects are trying to access
> those lists at the same time though...
>

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. Couldn't you join
the two arrays, then call MyJoinedArray.uniq!, then take the resulting
set and format it as you please? I know that you are doing more than
just that. I was mostly wondering why you would not use the built in
call.

···

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

I think a big part of it is that there are variations in what we assume the
questioner wanted.

In my case, I interpreted it as:
1) remove items that appear in both lists from both lists
     For instance, removeDups ([a, b, c, d], [b, d, f, g]) => [a, c], [f,
g]
2) don't go so far as remove more than the common count of dups
     For instance, removeDups ([a, a, b, b, c, d, d], [b, d, d, d, f, g, g])
=> [a, a, b, c], [d, f, g, g]
3) keep the lists in original order (probably not required but I'm not
sure)

I guess, it would be nice to have had the *need* demonstrated via example or
clearly stated..
but its been fun.

···

On 5/11/07, Lloyd Linklater <lloyd@2live4.com> 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. Couldn't you join
the two arrays, then call MyJoinedArray.uniq!, then take the resulting
set and format it as you please? I know that you are doing more than
just that. I was mostly wondering why you would not use the built in
call.

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

Lloyd Linklater 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

Kevin Compton wrote:

I think a big part of it is that there are variations in what we assume
the
questioner wanted.

In my case, I interpreted it as:
1) remove items that appear in both lists from both lists
     For instance, removeDups ([a, b, c, d], [b, d, f, g]) => [a, c],
[f,
g]
2) don't go so far as remove more than the common count of dups
     For instance, removeDups ([a, a, b, b, c, d, d], [b, d, d, d, f, g,
g])
=> [a, a, b, c], [d, f, g, g]
3) keep the lists in original order (probably not required but I'm not
sure)

I guess, it would be nice to have had the *need* demonstrated via
example or
clearly stated..
but its been fun.

I have to say that I am almost certainly being simplistic here but why
cannot we do something like this:

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

p a
p b

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

p c
p a
p b

result:
[1, 2, 3, 4]
[2, 4, 6, 8]
[2, 4]
[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/11/07, Lloyd Linklater <lloyd@2live4.com> wrote:

Kevin Compton wrote:
> I think a big part of it is that there are variations in what we assume
> the
> questioner wanted.
>
> In my case, I interpreted it as:
> 1) remove items that appear in both lists from both lists
> For instance, removeDups ([a, b, c, d], [b, d, f, g]) => [a, c],
> [f,
> g]
> 2) don't go so far as remove more than the common count of dups
> For instance, removeDups ([a, a, b, b, c, d, d], [b, d, d, d, f, g,
> g])
> => [a, a, b, c], [d, f, g, g]
> 3) keep the lists in original order (probably not required but I'm not
> sure)
>
> I guess, it would be nice to have had the *need* demonstrated via
> example or
> clearly stated..
> but its been fun.

I have to say that I am almost certainly being simplistic here but why
cannot we do something like this:

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

p a
p b

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

p c
p a
p b

result:
[1, 2, 3, 4]
[2, 4, 6, 8]
[2, 4]
[1, 3]
[6, 8]

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

--
http://www.kakueki.com/ruby/list.html
A Look into Japanese Ruby List in English

Harry Kakueki wrote:

What happens here? :slight_smile:
All 5's are deleted.

If you are asking about my example, there were no 5s in it to begin
with. As was observed earlier, I think that better examples would have
resulted in better code. I was mostly interested in finding a rubyish
way to make it happen with great simplicity. If there is something
slightly different needed, perhaps a tweak or two to the arrays before
applying the differences could handle it.

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!

···

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

Wow - this question generated lots of replies! I'm still reading through all
of them.

I have another idea, but not sure if this will work:

def RemoveDupsFromLists ( list1 , list2 )
    list1.each_item do | i |
        list2.each_item do | j |
            if !(list2[j].nil?) and list1[i] == list2[j]
                list1[i] = nil
                list2[j] = nil
            end
        end
    end
    list1.compact!
    list2.compact!
    return [ list1 , list2 ]
end

···

On 5/11/07, Lloyd Linklater <lloyd@2live4.com> wrote:

Harry Kakueki wrote:

> What happens here? :slight_smile:
> All 5's are deleted.

If you are asking about my example, there were no 5s in it to begin
with. As was observed earlier, I think that better examples would have
resulted in better code. I was mostly interested in finding a rubyish
way to make it happen with great simplicity. If there is something
slightly different needed, perhaps a tweak or two to the arrays before
applying the differences could handle it.

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!

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

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 Quizzes.

Harry

···

On 5/12/07, Lloyd Linklater <lloyd@2live4.com> 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!

Looks good to me!

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

···

On 5/11/07, Mike Steiner <mikejaysteiner@gmail.com> wrote:

Wow - this question generated lots of replies! I'm still reading through
all
of them.

I have another idea, but not sure if this will work:

def RemoveDupsFromLists ( list1 , list2 )
    list1.each_item do | i |
        list2.each_item do | j |
            if !(list2[j].nil?) and list1[i] == list2[j]
                list1[i] = nil
                list2[j] = nil
            end
        end
    end
    list1.compact!
    list2.compact!
    return [ list1 , list2 ]
end

On 5/11/07, Lloyd Linklater <lloyd@2live4.com> wrote:
>
> Harry Kakueki wrote:
>
> > What happens here? :slight_smile:
> > All 5's are deleted.
>
> If you are asking about my example, there were no 5s in it to begin
> with. As was observed earlier, I think that better examples would have
> resulted in better code. I was mostly interested in finding a rubyish
> way to make it happen with great simplicity. If there is something
> slightly different needed, perhaps a tweak or two to the arrays before
> applying the differences could handle it.
>
> 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!
>
> --
> Posted via http://www.ruby-forum.com/\.
>