How to get the four minimum values index of array


#1

Hi,I have a list of angle value, duplicate value is Allowed.
How to get the four minimum values index of array?

for example:

-- Array
arr = #(86, 93, 126, 173, 173, 86, 90)
-- result
res = #(1, 2, 6, 7)

any help will be appreciated


#2

Post can’t be empty


#3

@Serejah, thanks.

as you know, findItem method always returns the index of the first occurrence of the given value .
so it doesn’t work well here.

Your Test:

-- Array
arr = #(86, 93, 126, 173, 173, 86, 90)

sorted = sort (deepCopy arr)
-- result: #(86, 86, 90, 93, 126, 173, 173)

res = #( (findItem arr sorted[1]),  (findItem arr sorted[2]),  (findItem arr sorted[3]),  (findItem arr sorted[4])  )
-- result: #(1, 1, 7, 2)

-- what i want is
-- #(1, 2, 6, 7)

#4

One possible solution:

(
	fn GetMinimumArrayValues amount:1 array:#() =
	(
		tmp = deepcopy array
		mmax = (amax tmp)+1
		
		result = for j = 1 to amount collect
		(
			idx = finditem tmp (amin tmp)
			tmp[idx] = mmax
			idx
		)
		return result
	)
	
	GetMinimumArrayValues amount:4 array:#(86, 93, 126, 173, 173, 86, 90)
)

#5

@PolyTools3D, thanks!
it seems like work well, I am trying to understand your idea. and check it for more case.

Yeah, i got it. finditem will find the next.

tmp[idx] = mmax   -- pretty girl.

#6

i’d probably do it with an index sort

   (
	fn comparefn a b values: =
	(
		va = values[a];
		vb = values[b];
		if va < vb then -1 else if va > vb then 1 else 0;
	)	
		
	fn GetMinArrayValues amount:1 array:#() =
	(
		indices = for i = 1 to array.count collect i;
		qsort indices comparefn values:array;
		for i = 1 to amount collect indices[i];
	)	
	
	GetMinArrayValues amount:4 array:#(86, 93, 126, 173, 173, 86, 90);
)

#7

@Klvnk,Nice, so clear. Thanks


#8

i put all methods together in one test… including mine
see the difference:

/* PolyTools3D 	*****************************************/
fn getMinValuesIndexes_1 amount:1 list:#() =
(
	tmp = deepcopy list
	mmax = (amax tmp)+1
	
	result = for j = 1 to amount collect
	(
		idx = finditem tmp (amin tmp)
		tmp[idx] = mmax
		idx
	)
	result
)

/* Klvnk 		*****************************************/
fn comparefn a b values: =
(
	va = values[a];
	vb = values[b];
	if va < vb then -1 else if va > vb then 1 else 0;
)	
fn getMinValuesIndexes_2 amount:1 list:#() =
(
	indices = for i = 1 to list.count collect i;
	qsort indices comparefn values:list;
	indices;
)	


/* denisT 		*****************************************/
fn getMinValuesIndexes_3 list: =
(
	int32_class = dotnetclass "System.Int32[]"
	a = dotnet.valuetodotnetobject list int32_class
	b = dotnet.valuetodotnetobject (#{1..list.count} as array) int32_class
	a.sort a b
	b.clone()
)



(
	seed 0
	all_num = 100000
	min_num = 5000
	
	arr = for k=1 to all_num collect (random 0 1e6)
		
	gc()
	
	t0 = timestamp()
	h0 = heapfree
	
	result = getMinValuesIndexes_3 amount:min_num list:arr
	
	t1 = timestamp()
	h1 = heapfree
	
	mins = for k=1 to 10 collect arr[result[k]]
	
	format "% >> %(%) time:% heap:%\n" mins all_num min_num (t1 - t0) (h0 - h1)	
)	

my method has a serious problem with memory usage for big arrays. but it’s much faster