如何从长度为'n'的数组中删除等距元素以匹配给定长度'y'?

时间:2011-03-09 18:16:23

标签: arrays actionscript-3 algorithm

我们说我有数组foo和正整数y,其中foo.length> y。 我想从foo中移除元素,以便foo.length变为y(或非常接近它)。

另外,我需要保留foo的第一个和最后一个元素。被移除元素的索引必须尽可能相等地间隔开。 Foo可以切片,也可以用来创建新数组。

示例:如果foo = [a,b,c,d,e,f,g,1,2,3,4,5]y = 6,那么trimmedfoo可能是[a,c,e,g,2,4,5][a,c,e,2,4,5] ,但不是[a,c,e,g,2,4]因为foo的最后一个元素缺失。

伪代码解决方案很好,尽管as3是我选择的语言。 :)

谢谢!

5 个答案:

答案 0 :(得分:3)

假设您有一个长度为n的字符串,并且您希望它的长度为m。您可以选择n-2元素,并为新数组选择m-2个元素。现在,假设您当前已选择i个元素并已通过j个元素。如果i/j< (m-2)/(n-2)然后你落后了。你可能应该采取另一个元素。对于最大均匀选择,您真正想知道的是(i+1)/(j+1)i/(j+1)是否更接近您的目标(m-2)/(n-2)。如果溢出不是问题,你可以做一点代数来弄清楚这相当于(i+1)*(n-2) - (j+1)*(m-2)是多于还是小于(n-2)/2;更多意味着i更好(所以不要拿这个),而更少意味着i+1更好。

我不熟悉ActionScript,但是这里有一些希望可以作为伪代码使用的Scala:

// Don't worry about the [T: ClassManifest] thing
// that just means it can work on arrays of any type

def pare[T: ClassManifest](a: Array[T], m: Int) = {
  val b = new Array[T](m)
  val n2 = a.length - 2
  val m2 = m - 2
  b(0) = a(0)
  var i,j = 0
  while (j < n2) {
    val diff = (i+1)*n2 - (j+1)*m2
    if (diff < n2/2) {
      i += 1
      j += 1
      b(i) = a(j)
   }
   else j += 1
  }
  b(m2+1) = a(n2+1)
  b    // This means "return b"
}

让我们试一试!

scala> pare(Array[Any]('a','b','c','d','e','f','g',1,2,3,4,5),6)   
res1: Array[Any] = Array(a, c, e, 1, 3, 5)

scala> pare(Array(1,2,3,4,5,6,7,8,9),4)
res2: Array[Int] = Array(1, 4, 7, 9)

scala> pare(('a' to 'z').toArray, 16)
res3: Array[Char] = Array(a, b, d, f, h, i, k, m, n, p, r, t, u, w, y, z)

如您所见,这给出了非常均匀的间距。

答案 1 :(得分:1)

从foo的长度中减去y的值。 用减法结果除以foo的长度 - 然后调用结果N. 现在将数组复制到新数组并跳过而不复制每个第N个元素。 确保仅从第二个元素开始跳过元素并在最后一个元素之前停止(如果最后一个N'计数是最后一个元素,则跳过之前的元素)。

在上面的例子中: foo.length = 12,y = 6,N = 12-6 = 6,foo.length / N = 2

所以我们过去并移动每一个元素。

在其他示例中,我们可能需要跳过几个元素来修复除法的结果数组

答案 2 :(得分:1)

根据您的价值观和其他人进行测试,并且有效。

var originalArray:Array = ['a','b','c','d','e','f','g','1','2','3','4','5'];
var newLength:Number = 6;

var trimmedArray:Array = originalArray.filter(function(item:*, i:int, a:Array):Boolean {
    return  (((i + 1) % (a.length/newLength)) == 1) || (i == 0) || (i == a.length - 1);
});

trace(trimmedArray); // outputs a,c,e,g,2,4,5

答案 3 :(得分:1)

我已将Rex Kerr的精彩算法翻译成PHP,并希望将其发布在此处,因为我认为其他人更容易阅读。唯一真正的区别是,如果数组小于所需的数量,则返回数组:

private function evenlyReduceArray($originalArray, $desiredCount){

    if(count($originalArray) <= $desiredCount)
    {
        return $originalArray;
    }

    $newArray             = array();
    $trimmedLength        = count($originalArray) - 2;
    $trimmedDesiredCount  = $desiredCount - 2;

    $newArray[0] = $originalArray[0];

    $i = 0;
    $j = 0;
    while($j < $trimmedLength)
    {
        $diff = ($i + 1) * $trimmedLength - ($j + 1) * $trimmedDesiredCount;
        if($diff < $trimmedLength / 2)
        {
            $i += 1;
            $j += 1;
            $newArray[$i] = $originalArray[$j];
        }
        else{
            $j+= 1;
        }
    }

    $newArray[$trimmedDesiredCount + 1] = $originalArray[$trimmedLength + 1];

    return $newArray;
}

答案 4 :(得分:0)

如果第一个和最后一个元素是数组中唯一不可触摸的元素,那么更容易的方法是重复删除第二个和倒数第二个项目,直到达到所需的长度?

foo = [a,b,c,d,e,f,g,1,2,3,4,5];
y = 6;
loopType = 1;

while(foo.length>y)
{
    if(loopType==1)
    {
        foo[1].splice(1,1); //remove second item
        loopType = 2; //set loop to remove from other end of array
    }
    else
    {
        foo[1].splice(foo.length-2,1); //remove second-last item (foo.length-1 is the last item)
        loopType = 1; //set loop to remove from other end of array
    }
}

现在foo应该是[a,e,f,g,1,5];