 # 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.

``````-- 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),  (findItem arr sorted),  (findItem arr sorted),  (findItem arr sorted)  )
-- 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