J
NB. random array of floating-point numbers
] y =: 10 (?@$%]) 5
0 0.6 0.2 0.4 0.4 0.8 0.6 0.6 0.8 0
NB. count occurrences
({:,#)/.~ y
0 2
0.6 3
0.2 1
0.4 2
0.8 2
NB. order by occurrences
(\:{:"1)({:,#)/.~ y
0.6 3
0 2
0.4 2
0.8 2
0.2 1
NB. pick the most frequent
{.{.(\:{:"1)({:,#)/.~ y
0.6
Я бы посоветовал не использовать хеш, поскольку он предполагает точное сравнение - никогда не хорошее предположение для чисел с плавающей запятой. Вы всегда хотите сделать сравнение эпсилон в некотором роде. Что если в вашем массиве есть некоторые элементы 0.2(00000000)
и 0.2(00000001)
, которые на самом деле следует считать равными, но не потому, что они получены из разных вычислений?
Удобно, J всегда выполняет эпсилон-сравнение по умолчанию. Слишком удобно, поскольку он скрыт в /.~
, и мне нужно написать больше кода, чтобы продемонстрировать, как это сделать на других языках, таких как Python ...
epsilon = 0.0001
def almost_equal(a, b):
return -epsilon <= a-b <= epsilon
array = [0.0, 0.6, 0.2, 0.4, 0.4, 0.8, 0.6, 0.6, 0.8, 0.0]
# more efficient would be to keep this in sorted order,
# and use binary search to determine where to insert,
# but this is just a simple demo
counts = []
for a in array:
for i, (b, c) in enumerate(counts):
if almost_equal(a, b):
counts[i] = (b, c + 1)
break
else:
counts.append((a, 1))
# sort by frequency, extract key of most frequent
print "Mode is %f" % sorted(counts, key = lambda(a, b): b)[-1][0]