Notifications
Clear all
[Closed] How to get the four minimum values index of array
Mar 19, 2019 12:51 am
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
7 Replies
Mar 19, 2019 12:51 am
@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)
Mar 19, 2019 12:51 am
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)
)
Mar 19, 2019 12:51 am
@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.
Mar 19, 2019 12:51 am
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);
)
Mar 19, 2019 12:51 am
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