Get Unique Strings from an array

Hi there,

I have a simple question but can’t figure it out…
I was wondering how to create a new array from an existing array that would contain no duplicates…

I worked a bit on an example but it does not look very nice…

Any hint would be appreciated…

InputArray=newArray("Item1","Item2","Item3","Item1","Item2","Item4");
Array.show(InputArray);
waitForUser("Ready ?");

NbDuplicatedItems=0;
for (i=0; i<InputArray.length-1; i++){
for (n=i+1; n<InputArray.length; n++){
ItemI=InputArray[i];
ItemN=InputArray[n];
if(ItemI==ItemN && ItemI!=""){
InputArray[n]="";
NbDuplicatedItems++;
} // end of if
} // end of for n
} // end of for i

OutputArray1=InputArray;
Array.show(OutputArray1);

NbUniqueItems=InputArray.length - NbDuplicatedItems;
OutputArray2=newArray(NbUniqueItems)
n=0;
for (i=0; i<InputArray.length; i++){
  ItemI=InputArray[i];
  if(ItemI!=""){
    OutputArray2[n]=ItemI;
    n++;
  }
}
Array.show(OutputArray2);

OutputArrayExpected=newArray("Item1","Item2","Item3","Item4");
Array.show(OutputArrayExpected);

The easiest way is to use python. A set is a list (in Python mutable arrays are called lists) with unique items. the code will look like this (to be run as a Python script):

in_list = ["Item1","Item2","Item3","Item1","Item2","Item4"]
out_set = list(set(in_list))
print(in_list)
print(out_set)

You can use runMacro(name, arg) to use this inside an ImageJ macro:

Macro

result = runMacro("unique.py", "Item1,Item2,Item3,Item1,Item2,Item4");
IJ.log(result);

unique.py (saved inside the macros folder of ImageJ/Fiji)

result = ",".join(set(getArgument().split(',')))

The problem is, I don’t know any funtion in the IJ macro language that can convert an array to a string (like join() in Python) and back (like split()).

2 Likes

Hi

Michael

Thank you very much for your reply.
I don’t know much about Python but I have heard it is somehow intuitive programming language.
So if I understand correctly I can create a Python script to be saved in the macros folder. Then I can call and execute this Python script from within a ImageJ macro ?

To create a string from an array I would do:

MyArrayAsString="";
for(i=0;i<MyArray.length;i++){
    MyArrayAsString=MyArrayAsString+"\n"+MyArray[i];
} // end of for

Then use

OutputArray=split(MyArrayAsString,"\n");

You getting it right. You can run scripts written in different languages using runMacro(). When you use runMacro() for the first time, ImageJ will download a file that is required to run Python code. After that you have to restart ImageJ and running Python code is possible.

An alternative to runMacro() is eval("python", script). Then you don’t need an additional file. The drawback is the complex string that is needed to construct the command to run.

function unique(InputArray) {
    separator = "\\n"
    
    InputArrayAsString = InputArray[0];
    for(i = 1; i < InputArray.length; i++){
        InputArrayAsString += separator + InputArray[i];
    }
    
    script = "result = r'" + 
             separator +
             "'.join(set('" +
             InputArrayAsString +
             "'.split('" + 
             separator +
             "')))";
    
    result = eval("python", script);
    OutputArray = split(result, separator);
    return OutputArray;
}

InputArray=newArray("Item1","Item2","Item3","Item1","Item2","Item4");
OutputArray = unique(InputArray);
Array.show(OutputArray);

I have modified your for loop that creates an string from an array to not start with the separator.

To use \n as a separator it is necessary to escape it with another \. The r at the Python code is necessary to create a raw string, that includes the \n an a format the macro language can handle.

5 Likes

That’s terrific.
Thank you very much. I would not have come up with this solution for sure !

Hi Michael,

I am trying to implement your solution however, the result doesn’t seem to return to imageJ.

I created a python script with the line of code below :

list_pot_numbers = ",".join(set(getArgument().split(',')))

and I have an image J macro that allows me to select the python script and then runs your code

#@ File (label = "python pot number file") python_pot_finder_file
unique_pots = runMacro(python_pot_finder_file,"1,2,2,3,3,3,4,1");

print(unique_pots);
print("finished");

“Finished” is printed in the log windown with a blank line above it.

Have I made a mistake when I modified your code?

Kind regards,
Nima