我需要均匀从数组中选择 n 元素。我想最好的解释方法就是举例。
说我有:
数组[0,1,2,3,4]我需要选择3个数字.. 0,2,4。
当然,如果数组长度< = n ,我只需要返回整个数组。
我很确定有一个定义的算法,一直在尝试搜索,我看了算法简介但找不到满足我需求的东西(可能忽略了它) )
我遇到的问题是我无法找到一种方法将其扩展到任何数组[p..q],选择N个均匀元素。
注意:我不能只从上面的例子中选择偶数元素。
其他一些例子;
数组[0,1,2,3,4,5,6],3个元素;我需要得到0,3,6
数组[0,1,2,3,4,5],3个元素;我需要得到0,2或3和5
编辑:
更多例子:
数组[0,1,2],2元:0,2
数组[0,1,2,3,4,5,6,7],5元:0,2,3或4,5,7
是的,我想永远包括第一个和最后一个元素。
编辑2:
我在想的是......第一个+最后一个元素,然后使用中值继续工作。虽然我在试图这样做时感到困惑/困惑。
我会看看你发布的算法。谢谢!
编辑3:
这是使用PHP的 incrediman 解决方案的加强版本。也可以使用关联数组,同时保留键。
<?php
/**
* Selects $x elements (evenly distributed across $set) from $set
*
* @param $set array : array set to select from
* @param $x int : number of elements to select. positive integer
*
* @return array|bool : selected set, bool false on failure
*/
///FIXME when $x = 1 .. return median .. right now throws a warning, division by zero
function select ($set, $x) {
//check params
if (!is_array($set) || !is_int($x) || $x < 1)
return false;
$n = count($set);
if ($n <= $x)
return $set;
$selected = array ();
$step = ($n - 1) / ($x - 1);
$keys = array_keys ($set);
$values = array_values($set);
for ($i=0; $i<$x; $i++) {
$selected[$keys[round($step*$i)]] = $values[round($step*$i)];
}
return $selected;
}
?>
你可以实现一个Iterator,但我不需要那么做。
答案 0 :(得分:14)
享受! (伪代码):
function Algorithm(int N,array A)
float step=(A.size-1)/(N-1) //set step size
array R //declare return array
for (int i=0, i<N, i++)
R.push(A[round(step*i)]) //push each element of a position which is a
//multiple of step to R
return R
这里最容易犯的错误可能是将step
转换为整数或在开头将其舍入。但是,为了确保提取正确的元素,您必须将step
声明为浮点数,舍入倍数step
正在迭代数组。
php中的测试示例:
<?
function Algorithm($N,$A){
$step=(sizeof($A)-1)/($N-1);
for ($i=0;$i<$N;$i++)
echo $A[round($step*$i)]." ";
echo "\n";
}
//some of your test cases:
Algorithm(3,array(1,2,3));
Algorithm(5,array(0,1,2,3,4,5,6,7));
Algorithm(2,array(0,1,2));
Algorithm(3,array(0,1,2,3,4,5,6));
?>
Outputs:
1 2 3
0 2 4 5 7
0 2
0 3 6
(您可以在此处查看您的测试用例并尝试新的测试用例:http://codepad.org/2eZp98eD)
答案 1 :(得分:2)
让n+1
为您想要的元素数量,已经限定为数组的长度。
然后,您希望元素位于数组末尾的索引0/n
,1/n
,...,n/n
。
让m+1
为数组的长度。那么你的索引是round(m*i/n)
(用浮点完成除法)。
答案 2 :(得分:1)
您的步长为(ArraySize-1)/(N-1) 只需将步长添加到浮点累加器,并将累加器四舍五入以获得数组索引。重复直到累加器&gt;数组大小。
答案 3 :(得分:1)
您希望在列表中包含第一个和最后一个元素。
如果要从N个项目列表中提取X项目,步长将为(N-1)/(X-1)。当你拉出每一个时,你想要的只是圆形。
答案 4 :(得分:0)
基于@ Rex 的答案。 伪代码!甚至有人可能会说这是 JS
/// Selects |evenly spaced| elements from any given array. Handles all the edge cases.
function select(array: [Int], selectionCount: Int) {
let iterationCount = array.length - 1; // Number of iterations
let expectedToBeSelected = selectionCount - 1; // Number of elements to be selected
let resultsArray: [Int] = []; // Result Array
if (selectionCount < 1 || selectionCount > array.length) {
console.log("Invalid selection count!");
return resultsArray;
}
var i;
for (i in array) {
if (selectionCount == 1) {
resultsArray.push(array[i]);
break;
}
let selectedSoFar = Math.round(iterationCount * i / expectedToBeSelected);
if (selectedSoFar < array.length) {
resultsArray.push(array[selectedSoFar]);
} else {
break; // If selectedSoFar is greater than the length then do not proceed further.
}
}
return resultsArray;
}