CGTalk > Software > Autodesk Maya > Maya Programming
Login register
Thread Closed share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 01-07-2011, 09:42 PM   #1
sagunmanandhar
Veteran
no job
 
Join Date: Oct 2002
Posts: 32
Remove duplicates from INT/FLOAT array

hi,
im looking for something like stringArrayRemoveDuplicates() that works with int / float array. pls help
 
Old 01-08-2011, 01:19 AM   #2
NaughtyNathan
HighEnd3D deserter
 
NaughtyNathan's Avatar
Naughty Nathan
Technical Artist
Sony SCEE Liverpool
Manchester, United Kingdom
 
Join Date: May 2008
Posts: 2,608
this is not really a hard funtion to write yourself, but you may have already noticed that stringArrayRemoveDuplicates is actually a MEL script, not a command. As this is the case you can just open it up and copy it. then just modify it slightly to work on ints or floats depending on your needs (it must be one or the other as MEL must return a specific type.)

:nathaN
 
Old 01-13-2011, 08:56 PM   #3
norbertnacu
Frequenter
 
norbertnacu's Avatar
portfolio
Norbert Nacu
Unemployed
USA
 
Join Date: Nov 2009
Posts: 105
Post Something like this?

Code:
global proc int[] intArrayRemoveDuplicates( int $intArr[] ) { int $resuts[]; for( $intAr in $intArr ) { int $isFound = false; for( $resut in $resuts ) { if( $intAr == $resut ) { $isFound = true; break; } } if( $isFound == false ) $resuts[size($resuts)] = $intAr; } return $resuts; }

HTML Code:
intArrayRemoveDuplicates( {5, 5, 65, 65, 33, 22, 1} )



Code:
global proc float[] floatArrayRemoveDuplicates( float $floatArr[] ) { float $resuts[]; for( $floatAr in $floatArr ) { int $isFound = false; for( $resut in $resuts ) { if( $floatAr == $resut ) { $isFound = true; break; } } if( $isFound == false ) $resuts[size($resuts)] = $floatAr; } return $resuts; }

HTML Code:
floatArrayRemoveDuplicates( {1.0, 1.0, 2.5, 3.2, 2.5, 1.0, 58.88} )


Thank You,
nn
 
Old 01-14-2011, 03:58 PM   #4
ewerybody
w같t
 
ewerybody's Avatar
portfolio
eRiC Werner
pyroTechnical Artist
Berlin, Germany
 
Join Date: Jun 2003
Posts: 613
nice! could even be more elegant with also useful isInArray functions:

Code:
global proc float[] floatArrayRemoveDuplicates( float $array[] ) { float $resuts[]; int $count = 0; for( $item in $array ) if ( !isInFloatArray($item, $resuts) ) $resuts[$count++] = $item; return $resuts; } global proc int isInFloatArray( float $value, float $array[] ) { for ( $item in $array ) if ( $item == $value ) return true; return false; }
__________________
goodsoul.de
 
Old 01-14-2011, 07:56 PM   #5
Keilun
Expert
Keilun
Canada
 
Join Date: Aug 2005
Posts: 738
Given the limited precision of floats, the == operator on float isn't always what you want. Adding an optional tolerance value might be useful. I feel like there's something to that effect already in MEL somewhere, but I can't recall it.

Edit: Ah yes:

Code:
int equivalentTol(float $a, float $b, float $tol)


Examples:
Code:
equivalentTol(0.0, 0.0005, 0.001); // Result : 1 // equivalentTol(0.0, 0.005, 0.001); // Result : 0 //

Last edited by Keilun : 01-14-2011 at 08:00 PM.
 
Old 01-17-2011, 11:38 AM   #6
ewerybody
w같t
 
ewerybody's Avatar
portfolio
eRiC Werner
pyroTechnical Artist
Berlin, Germany
 
Join Date: Jun 2003
Posts: 613
hmm ... true but I'd rather implement that in an additional function to keep the real thing slim.

maybe like:
Code:
global proc float[] floatArrayRemoveDupTol( float $array[] , float $tol ) { float $resuts[]; int $count = 0; for( $item in $array ) if ( !isInFloatArrayTol($item, $resuts, $tol) ) $resuts[$count++] = $item; return $resuts; } global proc int isInFloatArrayTol( float $value, float $array[], float $tol ) { for ( $item in $array ) if ( equivalentTol($item, $value, $tol) ) return true; return false; } floatArrayRemoveDupTol({0.1, 0.10001, 0.2, 0.23}, 0.03); // Result: 0.1 0.2 //
__________________
goodsoul.de
 
Old 01-18-2011, 04:21 AM   #7
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
Quote:
Originally Posted by ewerybody
to keep the real thing slim...


Code:
floatArrayRemoveDupTol({0.07, 0.1, 0.04}, 0.03); floatArrayRemoveDupTol({0.04, 0.1, 0.07}, 0.03); // Result: ??? //

Last edited by denisT : 01-18-2011 at 04:29 AM.
 
Old 01-18-2011, 11:16 AM   #8
ewerybody
w같t
 
ewerybody's Avatar
portfolio
eRiC Werner
pyroTechnical Artist
Berlin, Germany
 
Join Date: Jun 2003
Posts: 613
ehmm... yes?
__________________
goodsoul.de
 
Old 01-18-2011, 05:49 PM   #9
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
Quote:
Originally Posted by denisT
Code:
floatArrayRemoveDupTol({0.07, 0.1, 0.04}, 0.03); floatArrayRemoveDupTol({0.04, 0.1, 0.07}, 0.03); // Result: ??? //


i just want to say that the method might be not accurate but it has not to depend on order of array items.
the solution #1 is to sort a float array before the removing duplicates using tolerance.
but the method i use is to ROUND array values using some precision, and collect only unique after that:
Code:
global proc float roundFloat (float $f, float $precision) { $f /= $precision; float $f1 = floor($f); float $f2 = ceil($f); float $v = (($f - $f1) > ($f2 - $f)) ? $f2 : $f1; return ($v*$precision); } global proc int findFloatItem (float $item, float $array[]) { for ($k = 0; $k < size($array); $k++) if ($item == $array[$k]) return $k; return -1; }; global proc float[] uniqueRoundFloatArray (float $array[], float $precision) { float $arr[], $i; for ($item in $array) { $i = roundFloat($item, $precision); if (findFloatItem($i,$arr) == -1) $arr[size($arr)] = $i; } return $arr; // return (sort($arr)); // if you like } uniqueRoundFloatArray ({0.1, 0.10001, 0.2, 0.23}, 0.1); // Result:0.1 0.2// uniqueRoundFloatArray ({0.1, 0.10001, 0.2, 0.23}, 0.01); // Result:0.1 0.2 0.23//

Last edited by denisT : 01-18-2011 at 06:04 PM.
 
Old 01-18-2011, 09:26 PM   #10
haggi
Expert
3d freelancer
 
Join Date: Apr 2004
Posts: 1,064
Okay, this is maybe a little bit overdone but it works:

Code:
global float $ffArray[] = {1.0, 2.3, 4.4, 99, 2.3, 4, 2.3}; float $sorted[] = python("import pymel.core as pm; list(set((pm.getMelGlobal(\"float[]\", \"$ffArray\"))))"); print $sorted;
 
Old 01-19-2011, 10:41 AM   #11
ewerybody
w같t
 
ewerybody's Avatar
portfolio
eRiC Werner
pyroTechnical Artist
Berlin, Germany
 
Join Date: Jun 2003
Posts: 613
@denis: true but I wasn't asking for a uniquifier with tolerance ;] this just was an example for the closest way to go.

@haggi: wow! But this doesn't fix the tolerance thing or does it? I'm too scared to try
__________________
goodsoul.de
 
Old 01-19-2011, 01:45 PM   #12
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,637
Send a message via ICQ to denisT
Quote:
Originally Posted by ewerybody
@denis: true but I wasn't asking for a uniquifier with tolerance ;] this just was an example for the closest way to go.

i wasn't answering to you. i just tried to warn against using a shortest way rather than the right one.
 
Old 01-19-2011, 03:12 PM   #13
ewerybody
w같t
 
ewerybody's Avatar
portfolio
eRiC Werner
pyroTechnical Artist
Berlin, Germany
 
Join Date: Jun 2003
Posts: 613
Quote:
Originally Posted by denisT
i wasn't answering to you.

thats right. You qouted me and then said something seeming unrelated ??? Instead of saying what the problem is. Which I understand as well: A tolerance might not be what you want: You might want to truncate the floats decimal places and check against that. Which is a more understandable way indeed!

I'm just saying that It was not my idea but Keiluns. I never needed a function like that.

But as I think about that I remember a very cool function Nathan gave me and I think giving the number of decimals to keep is even more obvious.:

Code:
global proc int nRound(float $input) { return trunc($input + (0.5 * sign($input)) ); } global proc float cutFloat(float $float, int $decimals) { int $factor = pow(10,$decimals); return ((float)nRound($float * $factor) / $factor); } global proc int isInFloatArray( float $value, float $array[] ) { for ( $item in $array ) if ( $item == $value ) return true; return false; } global proc float[] floatArrayRemoveDuplicates2( float $array[] , float $decimals ) { float $resuts[], $f; int $count = 0; for( $item in $array ) { $f = cutFloat($item, $decimals); if ( !isInFloatArray($f, $resuts) ) $resuts[$count++] = $f; } return $resuts; } floatArrayRemoveDuplicates2({0.1, 0.10001, 0.2, 0.23}, 1); // Result:0.1 0.2// floatArrayRemoveDuplicates2({0.1, 0.10001, 0.2, 0.23}, 2); // Result:0.1 0.2 0.23//


The sorting thing I'd leave to the user. Putting a sort() around his stuff wouldn't be too much to ask I guess

Code:
$aFloatArray = {0.1, 0.10001, 0.23, 0.2, 0.79, 0.7, 0.71}; floatArrayRemoveDuplicates2($aFloatArray, 1); // Result: 0.1 0.23 0.2 0.79 0.7 // floatArrayRemoveDuplicates2(sort($aFloatArray), 1); // Result: 0.1 0.2 0.7 0.79 // sort(floatArrayRemoveDuplicates2($aFloatArray, 1)); // Result: 0.1 0.2 0.23 0.7 0.79 //
__________________
goodsoul.de

Last edited by ewerybody : 01-19-2011 at 05:06 PM.
 
Old 01-19-2011, 04:41 PM   #14
isoparmB
Wave man
 
isoparmB's Avatar
Martin
wandering in Singapore
Makati, Philippines
 
Join Date: Nov 2005
Posts: 868
If you wanted to cheat though:

Code:
float $floater[] = {12.0, 15.2, 15.21, 22.0, 86.062, 178.0, 12.01, 22.01}; int $precision = 1; string $feeder = ""; int $i = 0; for( $i = 0; $i <=(`size $floater` - 1); $i++) { $feeder += $floater[$i] + ","; } float $result[] = python("list(set( [ round(float(x), " + $precision + ") for x in [" + $feeder + "] ] ) )"); print $result;


Or you could write it simply as straight python.
Cheers.
__________________
...everything will be fine, as long as nothing goes wrong...

Last edited by isoparmB : 01-19-2011 at 04:45 PM.
 
Old 01-19-2011, 05:02 PM   #15
ewerybody
w같t
 
ewerybody's Avatar
portfolio
eRiC Werner
pyroTechnical Artist
Berlin, Germany
 
Join Date: Jun 2003
Posts: 613
Quote:
Originally Posted by isoparmB
Or you could write it simply as straight python.
hehe yea so true.
__________________
goodsoul.de
 
Thread Closed share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 05:08 AM.


Powered by vBulletin
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd.