array: remove same values?

   9771   10   2
User Avatar
Member
1075 posts
Joined: April 2017
Offline
Hi!

If I have an array like this:

{0,1,2,2,7,9,9,9,33}

…How can I remove all the same values to end up with:

(0,1,2,7,9,33)

?

-Olivier
User Avatar
Member
459 posts
Joined: Oct. 2011
Offline
You could do it in python:
geo = hou.pwd().geometry()

my_list = geo.intListAttribValue('my_list') # Get the detail attribute
no_duplicates = list(set(my_list)) # Remove duplicates
geo.setGlobalAttribValue('my_list', no_duplicates) # Store the new values

This example runs in a Python SOP and the geo is just one point with a detail array attribute

-b
http://www.racecar.no [www.racecar.no]
User Avatar
Member
1075 posts
Joined: April 2017
Offline
Thanks but I'm looking for a Vex solution. I'm new to coding so i'd like to keep it simple by staying with Vex.

-Olivier
User Avatar
Member
2129 posts
Joined: Sept. 2015
Offline
Yes…in a wrangle set to detail:


//i[]@List = {4,5,8,8,2,3,0,1};
//i[]@List = {4,4,8,8,2,3,8,4,8};
i[]@List = {1,8,8,2,7,3,8,4,8,6,7,1,1};


int Count, Count_A;


for(Count = 0; Count < len(i[]@List); Count++)
{
for(Count_A = 0; Count_A < len(i[]@List); Count_A++)
{
if( (i[]@List[Count] == i[]@List[Count_A]) && (Count != Count_A) )
{
removeindex(i@List, Count_A);
}
}
}
User Avatar
Member
1075 posts
Joined: April 2017
Offline
That's more complicated than I expected!

Thanks, I'll use this very soon.

-Olivier
User Avatar
Member
2129 posts
Joined: Sept. 2015
Offline
In case your interested…maybe if this is the only code in a wrangle that one is going to use…it's not too bad that it's ‘complicated’…but if your going to need to do other things in the same wrangle, what I like to do as in this case where I know as in this case, that this code is like to be used elsewhere, is to make it an ‘external’ function.

So with the above what you could do is copy and paste into a text file, with some modifications to make it like this:



int[] Remove_Duplicate_Array_Items(int Imported_Array[])
{
int List[];
int Count, Count_A;

List = Imported_Array;

for(Count = 0; Count < len(List); Count++)
{
for(Count_A = 0; Count_A < len(List); Count_A++)
{
if( (List[Count] == List[Count_A]) && (Count != Count_A) )
{
removeindex(List, Count_A);
}
}
}

return List;
}

Then save it as a text file with an extension of your preference…I like to use *.h as personal convention.

For my project, because I work as a ‘freelancer’ and not in a production team I tend to keep all files within/reference to the project $HIP directory.

In that directory I create a folder named ‘vex’ and within that folder another one named ‘include’ within that I place the above file/s with my .h extensions.

Then in any wrangle of my project file the first line is as follows:

#include <Remove_Duplicate_Array_Items.h>

and after that I only need to use one line to make use of the function which keeps it looking simpler to read and add more code/other functions:

#include <Remove_Duplicate_Array_Items.h>

//i[]@List = {4,5,8,8,2,3,0,1};
//i[]@List = {4,4,8,8,2,3,8,4,8};
i[]@List = {1,8,8,2,7,3,8,4,8,6,7,1,1};


i[]@List = Remove_Duplicate_Array_Items(i[]@List);

Also, just to be clear of another convention I do…I tend to name the text file (with the .h extension) the same name as the function…for easy and quickly identifying my needs since if I want to use other functions I may have created is just a matter of adding additional #include lines:

#include <Remove_Duplicate_Array_Items.h>
#include <Another_One_Of_My_Functions.h>
#include <One_Thousand_Line_Function.h>

//Happy coding here;
User Avatar
Member
1075 posts
Joined: April 2017
Offline
Wow, that's very cool! I'm only a beginner in Houdini so this might be too advanced for the simple personal tests I'm doing. That being said, it's nice that you can create your own functions! It's like creating digital assets for vex coding!

Cheers!

-Olivier
User Avatar
Member
36 posts
Joined: Nov. 2013
Offline
I was just looking for vex solution and found this thread...
Just in case anyone else is looking for this, maybe here is another, shorter solution:

f[]@myarray = {1,1,1,2,2,3,4,5,5,5,6,7,7,7,8,8,9};

float current;
float next;

for(int i = len(@myarray); i > -1; i--)
    {
    current = @myarray[i];
    next = @myarray[i-1];
    if(current == next)
        {
        removeindex(@myarray, i);
        }
    }


Another way could be to assign a value like "0" to the duplicate values instead of removing..
Edited by Fele - Sept. 29, 2021 07:41:33
User Avatar
Member
5 posts
Joined: Jan. 2019
Offline
you can also do this way:

int origLs = {1,1,1,2,2,3,4,5,5,5,6,7,7,7,8,8,9};
int setOrigLs = array();
foreach(int orig; origLs)
{
if (find(setOrigLs, orig) < 0)
append(setOrigLs, orig);
}
origLs = setOrigLs;
Grant Lee
User Avatar
Member
3 posts
Joined: March 2019
Offline
evrstudio
you can also do this way:

int origLs = {1,1,1,2,2,3,4,5,5,5,6,7,7,7,8,8,9};
int setOrigLs = array();
foreach(int orig; origLs)
{
if (find(setOrigLs, orig) < 0)
append(setOrigLs, orig);
}
origLs = setOrigLs;

This worked for me. Really smart!
User Avatar
Member
192 posts
Joined: April 2015
Offline
Thank you.

int origLs[] = {1,1,1,2,2,3,4,5,5,5,6,7,7,7,8,8,9};
int setOrigLs[];
foreach(int orig; origLs){
    if (find(setOrigLs, orig) < 0) append(setOrigLs, orig);
}
origLs = setOrigLs;
  • Quick Links