Search code examples
javascriptadobe-illustratorextendscript

How can I extract duplicates from an array using ExtendScript?


I am trying to identify duplicate object names in an Illustrator file using ExtendScript so I can group them. I can get an array of all PageItems on a layer, I just don't know how to identify and store duplicates so I can perform the group operation.

This is a rather pathetic attempt at doing what I want:

var aLayer = app.activeDocument.activeLayer;
var pageItemsRef = aLayer.pageItems;
var duplicateNames = [];
var currentName;

for (var i = 0, len = pageItemsRef.length; i < len; i++) {
    if(i==0){
        currentName = pageItemsRef[0].name;
        continue;
    }
    if(pageItemsRef[i].name == currentName){
        var ref = {name:pageItemsRef[i].name, index:i}
        duplicateNames.push(ref);
    }
}

Continuing with this code will only give me consecutive duplicates. Sorry for the low quality example but I just don't know where to start.

I just want to iterate pageItemsRef and store the name + ID into separate arrays.

So array [0] will have 2+ duplicates stored as objects (Name, ID) Array [1] might have 5+ duplicates stored as objects also stored as (Name,ID) etc.

Any more efficient approaches are warmly welcomed as well. I am new to ExtendScript.

Any help greatly appreciated.


Solution

  • I'd propose this classic solution via the intermediate object obj. Since an object can't have keys with the same name it can be used as a 'filter' to gather into a value the items with the same property (a name in this case):

    var layer = app.activeDocument.activeLayer;
    var items = layer.pageItems;
    
    // the intermediate object {name1:[items], name2:[items], ...}
    var obj = {};
    for (var i=0; i<items.length; i++) {
        var item = items[i];
        var info = {name:item.name, id:item.uuid};  // <-- ID is .uuid ???
        if (item.name in obj) obj[item.name].push(info);
        else obj[item.name] = [info];
    }
    
    // make the 2d-array from the keys of the intermediate object
    // [ [{name1,id1},{name1,id2}], [{name2,id3},{name2,id4},...], ... ]
    var duplicates = [];
    for (var key in obj) duplicates.push(obj[key]); // <-- here we go
    
    // probably you don't even need the array
    // perhaps you can use the obj instead
    

    The only thing I don't get: what do you mean by 'ID'? In my code I'm using the native uuid property of a page item. Or do you mean just the plain counter (index)?