Is there any simple Python method to cull near-duplicate numbers (within tolerance) within a list? I could for example create a list of 3dpoints with the x coordinate of the points as the value from the list (and the y, z as 0) and then use rs.CullDuplicatePoints, but that seems like a kind of kludge…
Also thought of sorting the list and then iterating over it and if the neighbor to the right is within tolerance, eliminate it… not that easy either… Is there a better/smarter way?
At first I wasn’t sure whether you were talking about a list of scalars or a list of points, but after careful re-reading I concluded: scalars.
It seems to me that to accomplish your goal you will need to pair-wise compare each number with every other number to test for difference within tolerance, That’s pretty much what sorting does, but without the tolerance, and the library routines and functions to do it are pretty well optimized for speed. Once you have a sorted list, one pass through it testing for tolerance between one number and the next, throwing out those that don’t pass before moving to the next number in the list that isn’t within tolerance sounds to me like a pretty good method. So I think you are right. I guess that means I don’t know of a better/smarter way either.
Thanks, I was actually looking for CullDuplicateNumbers as CullDuplicatePoints is already implemented in rhinoscriptsyntax in Python. What I came up with are two methods, one home-grown “sort-and-compare” method, the other using rs.CullDuplicatePoints as a cheat:
import rhinoscriptsyntax as rs
import Rhino
def CullDuplicateNumbers(nums,tol):
nums.sort()
unique=[nums[0]]
for i in range(len(nums)-1):
if abs(nums[i+1]-unique[-1])>=tol:
unique.append(nums[i+1])
return unique
def CullDuplicateNumbersRS(nums,tol):
pts=[Rhino.Geometry.Point3d(0,0,num) for num in nums]
pts=rs.CullDuplicatePoints(pts,tol)
return [pt.Z for pt in pts]
numList=[1.0,1.11,1.0,2.0,4.0,1.2,3.0,5.0,7.0,1,1.1,1.2,1.09,1.3]
tolerance=0.1
print CullDuplicateNumbers(numList,tolerance)
>>>[1.0, 1.1, 1.3, 2.0, 3.0, 4.0, 5.0, 7.0]
print CullDuplicateNumbersRS(numList,tolerance)
>>>[1.0, 1.1, 1.3, 2.0, 3.0, 4.0, 5.0, 7.0]