Removing duplicate items from an array using the Array.filter() method

by Peter deHaan on August 5, 2007

in Array, ArrayCollection

I’m sure there is an easier/better way to do this (and I’ll update this post accordingly if I find one) but here is a little sample which takes an array of items and filters out the duplicates.

Full code after the jump.

View MXML

<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/08/05/removing-duplicate-items-from-an-array-using-the-arrayfilter-method/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="vertical"
        verticalAlign="middle"
        backgroundColor="white"
        creationComplete="init()">

    <mx:Script>
        <![CDATA[
            private var keys:Object = {};

            /**
             * Called by the Application container's creationComplete
             * event handler. This method creates a new Array object
             * which will be used as a data provider as well as a
             * filtered view of that array which does not contain
             * duplicated items.
             */
            private function init():void {
                /* Create a dummy data source with some semi-random
                    data. */
                var arr:Array = [];
                arr.push({data:1, label:"one"});
                arr.push({data:1, label:"one"});
                arr.push({data:1, label:"one"});
                arr.push({data:1, label:"one"});
                arr.push({data:2, label:"two"});
                arr.push({data:2, label:"two"});
                arr.push({data:2, label:"two"});
                arr.push({data:1, label:"one"});
                arr.push({data:3, label:"three"});
                arr.push({data:3, label:"three"});

                /* Filter the original array and call the
                    removeDuplicates() function on each item
                    in the array. */
                var filteredArr:Array = arr.filter(removedDuplicates);

                arrColl.source = arr;
                dedupedArrColl.source = filteredArr;
            }

            /**
             * This method is used to filter an array so that no
             * duplicate items are created. It works by first
             * checking to see if a keys object already contains
             * a key equal to the current value of the item.data
             * value. If the key already exists, the  current item
             * will not be readded to the data provider. If the key
             * does not already exist, add the key to the keys
             * object and add this item to the data provider.
             */
            private function removedDuplicates(item:Object, idx:uint, arr:Array):Boolean {
                if (keys.hasOwnProperty(item.data)) {
                    /* If the keys Object already has this property,
                        return false and discard this item. */
                    return false;
                } else {
                    /* Else the keys Object does *NOT* already have
                        this key, so add this item to the new data
                        provider. */
                    keys[item.data] = item;
                    return true;
                }
            }
        ]]>
    </mx:Script>

    <mx:ArrayCollection id="arrColl" />
    <mx:ArrayCollection id="dedupedArrColl" />

    <mx:HBox>
        <mx:VBox>
            <mx:Label text="Original ({arrColl.length} items):" />
            <mx:List dataProvider="{arrColl}" />
        </mx:VBox>
        <mx:VBox>
            <mx:Label text="Filtered ({dedupedArrColl.length} items):" />
            <mx:List dataProvider="{dedupedArrColl}" />
        </mx:VBox>
    </mx:HBox>

</mx:Application>

View source is enabled in the following example.

{ 6 comments… read them below or add one }

1 FlexLover August 5, 2007 at 1:35 pm

Tank’you very much, this is the right example for me.

Reply

2 Bob August 6, 2007 at 9:37 am

Nice example! Can this be done with an ArrayCollection as well?

Reply

3 peterd August 6, 2007 at 10:05 am

Bob,

I believe it can.

Try something like this:

dedupedArrColl = new ArrayCollection(arr);
dedupedArrColl.filterFunction = removedDuplicates;
dedupedArrColl.refresh();

And then change the filtering function to this:

/** Note that the method has 1 parameter now instead of 3, the rest of the code can remain the same */
private function removedDuplicates(item:Object):Boolean {
   // ...
}

Reply

4 Yuri August 7, 2009 at 6:08 am

Thanks, man! That’s what I needed here. Awesome!

Reply

5 ixdl January 13, 2010 at 5:27 pm

Bob,
let’s say you have an ArrayCollection AC with Strings S.
To make sure that each String is represented only once:

S=”Bob”;
if ( !AC.contains(S)) AC.addItem(S);

Reply

6 Aviral Sharma January 21, 2010 at 4:11 pm

If you wanna use the filter function twice, you might wanna clear the keys object since it already has old values for second use.

Snippet:

keys={};
var filterRoutes:Array = routesArray.filter(removedDuplicates);
keys={};
var filterDivisions:Array = divisionsArray.filter(removedDuplicates);

Reply

Leave a Comment

Sorry, this blog is terrible at eating HTML comments.
If you're pasting any HTML/XML/MXML code, you need to convert your < characters to &lt; and your > characters to &gt; .

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Anti-Spam Protection by WP-SpamFree

Previous post:

Next post: