ActionScript - Сравнение и удаление дубликатов сложных массивов? - PullRequest
3 голосов
/ 28 августа 2011

при сравнении простых массивов я использую что-то вроде следующей функции для объединения и удаления дубликатов:

//Merge
public function merge(a1:Array, a2:Array):Array
{
    var result:Array = a1.concat(a2);

    var dictionary:Dictionary = new Dictionary();

    for each    (var item:Object in result)
                dictionary[item] = true;

    result = new Array();

    for (var key:Object in dictionary)
        result.push(key);

    dictionary = null;

    return result;
}

однако, этот подход не работает на сложных массивах.

существует ли хорошо известный алгоритм, или вообще возможно написать функцию рекурсии, которая может сравнивать Vector.<Object> с другой? тот, который всегда будет работать, даже если сравниваемые объекты имеют дополнительные пары ключ / значение?


[EDIT]


, чтобы быть более ясным, используя словарь, чтобы определить, работают ли элементы в простом массиве только с примитивными типами данных (int, number, string и т. Д.) Или ссылками на объекты, поэтому приведенный выше пример работает, если передано 2 массива, напоминающих как то так:

var arr1:Array = new Array(1, 2, 3, 4, 5);
var arr2:Array = new Array(8, 7, 6, 5, 4);

, в результате чего получается объединенный массив со следующими значениями:

1, 2, 3, 8, 7, 6, 5, 4
В отличие от

, я спрашиваю, можно ли передать функции 2 сложных массива или Vector.<Object>, все из которых содержат уникальные объекты, которые могут иметь идентичные пары ключ / значение, и удалить избыточность в результирующем Vector.<Object>. например:

var vec1:Vector.<Object> = new Vector.<Object>();
vec1.push({city:"Montreal", country:"Canada"});
vec1.push({city:"Halifax", country:"Canada"});

var vec2:Vector.<Object> = new Vector.<Object>();
vec2.push({city:"Halifax", country:"Canada"});
vec2.push({city:"Toronto", country:"Canada"});

объединение двух вышеупомянутых векторных объектов приведет к следующему вектору путем определения и удаления объектов с одинаковыми парами ключ / значение:

{city:"Montreal", country:"Canada"}
{city:"Halifax", country:"Canada"}
{city:"Toronto", country:"Canada"}

Я ищу алгоритм, который мог бы обрабатывать удаление этих похожих объектов, не зная об их конкретных именах ключ / значение или о количестве пар ключ / значение в объекте.

1 Ответ

3 голосов
/ 29 августа 2011

Конечно, вы можете создать аналогичный пример с любым типом вектора:

     public function mergeObjectVectors(v1:Vector.<Object>,                      
                                        v2:Vector.<Object>):Vector.<Object>
     {
        var dictionary:Dictionary = new Dictionary();
        var concat:Vector.<Object> = v1.concat(v2);
        var result:Vector.<Object> = new Vector.<Object>();

        for each(var i:Object in concat)
        {
            if (!dictionary[i])
            {
                dictionary[i] = true;
                result.push(i);
            }
        }           

        return result;
    } 

Однако, если вы планируете принимать векторы любого типа, все будет иначе:

        public function testing():void
        {
             var v1:Vector.<Object> = new Vector.<Object>();
             v1.push({name:"Object 1"});
             v1.push({name:"Object 2"});

             // Vector w duplicates
             var v2:Vector.<Object> = new Vector.<Object>();
             var o:Object = {name:"Object 3"};                 
             v2.push(o);
             v2.push(o);
             v2.push(o);

             var resultVector:Vector.<Object> = mergeAnything(v1, v2, Class(Vector.<Object>));
             var resultArray:Array = mergeAnything(v1, v2, Array);
             var resultObject:Object = mergeAnything(v1, v2, Object);
        }


        public function mergeAnything(o1:Object, o2:Object, resultClass:Class):*
        {

            var dictionary:Dictionary = new Dictionary();
            var result:Object = new resultClass();

            var i:int;
            for each(var o:Object in o1)
            {
               if (!dictionary[o])
               {
                  dictionary[o] = true;
                  result[i++] = o;
               }
            }   

            for each(o in o2)
            {
               if (!dictionary[o])
               {
                  dictionary[o] = true;
                  result[i++] = o;
               }
            }

            return result;
        }

Первый пример будет более ресурсоэффективным.


EDIT: Это должно сделать это, попробуйте это на вашем примере:

     public function mergeObjectVectors(v1:Vector.<Object>, v2:Vector.<Object>):Vector.<Object>
    {
        var concat:Vector.<Object> = v1.concat(v2);
        var result:Vector.<Object> = new Vector.<Object>();

        var n:int = concat.length;
        loop:for (var i:int = 0; i < n; i++)
        {   
            var objectToAdd:Object = concat[i];

            var m:int = result.length;
            for (var j:int = 0; j < m; j++)
            {
                var addedObject:Object = result[j];
                if (this.areObjectsIdentical(objectToAdd, addedObject))
                {
                    continue loop;
                }
            }
            result.push(objectToAdd);
        }           

        return result;
    } 

    private function areObjectsIdentical(o1:Object, o2:Object):Boolean
    {
        var numComparisons:int = 0;

        for (var s:String in o1)
        {
            numComparisons++;
            if (o1[s] != o2[s])
            {
                return false;
            }
        }                   
        for (s in o2)
        {
            numComparisons--;
        }

        return !numComparisons;     
    }
...