How to flatten an array in Photoshop?

Viewed 433

Here is my code :

var doc = app.activeDocument;
var allLayers = new Array;
var allLayers = collectAllLayers(doc, allLayers);

function collectAllLayers (doc, allLayers){
    for (var m = 0; m < doc.layers.length; m++){
        var theLayer = doc.layers[m];
        if (theLayer.typename === "ArtLayer"){
            allLayers.push(theLayer);
        }else{
            collectAllLayers(theLayer, allLayers);
        }
    }
    return allLayers;
}
alert("array_layers : " + allLayers);

I am getting in alert array like this

[Layer1],[Layer2],[Layer3];

and I want make it looks like this :

[Layer1,Layer2,Layer3];

Thanks for answers and help in advance!

5 Answers

The code in question already works correctly. Referring to the documentation on ArtLayer, you can prove this by printing some of the properties for each of the objects in the array:

function collectAllLayers (layerSet, layers){
    for (var i = 0; i < layerSet.layers.length; i++){
        var layer = layerSet.layers[i];

        if (layer.typename === "ArtLayer"){
            layers.push(layer);
        } else {
            collectAllLayers(layer, layers);
        }
    }

    return layers;
}

function printable (artLayers) {
    var layerDescriptions = [];

    for (var i = 0; i < artLayers.length; i++) {
        var layer = artLayers[i];

        layerDescriptions.push(
            '{ name: ' + layer.name +
            ', kind: ' + layer.kind +
            ', opacity: ' + layer.opacity +
            ', visible: ' + layer.visible +
            ' }'
        );
    }

    return layerDescriptions;
}

var artLayers = collectAllLayers(app.activeDocument, []);
var layerDescriptions = printable(artLayers);

alert(layerDescriptions);

Code in the question do display single level array of ArtLayer objects. One can be confused, because toString method of ArtLayer object returns name of the layer in square brackets (in version of PS that I have installed (v19.1.5), "ArtLayer" string is displayed before layer name, but still inside square brackets). For example:

var doc = app.activeDocument;
alert(doc.layers[0]); // Alerts "[ArtLayer Layer 1]"

Alert window

To flatten array ary you can use [].concat.apply([], ary), like in:

var ary = [1, ["A", "B", "C"], 3];
alert(ary[2]); // Alerts "3"
alert([].concat.apply([],ary)[2]); // Alerts "B"

How about using the allLayers.push(theLayer[0]); instead of allLayers.push(theLayer);.

Have you tried to flat the list in the recursive result?

var doc = app.activeDocument;
var allLayers = new Array;
var allLayers = collectAllLayers(doc, allLayers);

function collectAllLayers (doc, allLayers){
    for (var m = 0; m < doc.layers.length; m++){
        var theLayer = doc.layers[m];
        if (theLayer.typename === "ArtLayer"){
            allLayers.push(theLayer);
        }else{
            flatten(collectAllLayers(theLayer, allLayers));
        }
    }
    return flatten(allLayers);
}

function flatten(arr) {return arr.reduce(
  (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
)};

alert("array_layers : " + allLayers);

you can use

const flatten = (layers, allLayers) => layers.reduce((acc,layer) => (Array.isArray(layer)) ? collectAllLayers(layer, acc) : acc.push(layer), allLayers);

const collectAllLayers = (doc, allLayers) => flatten(doc.layers, allLayers);
Related