-1

特定の配列があるとしましょう:

ary = [0, 1, 2, 4, 5, 6];

これは範囲に使用される配列で、最初の範囲は 0 から 1、2 番目の範囲は 1 から 2 などです。配列は、どの値も前の値より小さくならないように構築されていますが、等しい場合もあります。

最初と最後の配列項目は静的であり、変更されることはありません。したがって、範囲の合計は常に 6 です。

function rangeSum(a){
    var sum = 0;
    for(var i = 0; i< a.length-1;i++){
        sum += a[i+1]-a[i];
    }
    return sum; //Always equals 6 with this array
}

今、私は単一の範囲を変更したい:

ary  = [0, 1, 2, 4, 5, 6];
ary2 = [0, 1, 3, 4, 5, 6]; //Increases the second range with 1, reduces the third range with 1, the rest are unchanged

相互の範囲サイズを維持しながら、3 番目の範囲の削減を取り、それを残りの範囲に均等に広げる関数が必要です。

したがって、次のようになる代わりに:

ary  = [0, 1, 2, 4, 5, 6];       //Range [1, 1, 2,   1,    1]
ary2 = [0, 1, 3, 4, 5, 6];       //Range [1, 2, 1,   1,    1]

我々が得る

ary2 = [0, 1, 3, 4.5, 5.25, 6];  //Range [1, 2, 1.5, 0.75, 0.75]

例:

function shiftRange(array, index, increase){
    //Compute new array

    return ary2;
}

ary2 = shiftRange(ary, 2, 1);

この関数は、任意の配列サイズ、任意のインデックス (最初と最後を除く)、および負の数で動作する必要があります。

これは私が動作させようとした最新のコードですが、おそらく必要以上に複雑になり、まったく動作しません: http://jsfiddle.net/FN6TX/

誰かが助けてくれることを願っています:=)

4

2 に答える 2

1

変更が必要な配列の部分だけを考えてみましょう:

arr = [2, 4, 5, 6]

2 から 6 になります。この配列を変換して、すべての要素が互いに同じ比率で、3 から 6 になるようにします。

元のデータをデカルト グラフの横軸に、新しいデータを縦軸にすると、代数的に考えることができます。あなたは確かに 2 が 3 になる必要があることを知っています (したがって、あなたの行はその(2, 3)中にあります)、そしてあなたは確かに 6 が 6 のままであるべきであることを知っています (あなたの行は(6, 6)です)。

この直線の方程式は

function transform(x) {
    return (6 + 3 * x) / 4;
}

次に、次の方法で配列を変換できます。

for (var i = 0; i < 4; i++) {
    arr[i] = transform(arr[i]);
}

もちろん、上記の63、および (2 つの異なる)を一般化し、4配列のサブセットでのみ実行されるようにコードを適応させることができます。ただし、乗算はこの種の変換に非常に適しています。「何かを均等に広げたい」場合は常に乗算が必要です。フィドルで行っているように、変更を追跡する必要はありません。

更新: 静かな朝、おそらく: http://jsfiddle.net/FN6TX/1/であなたのフィドルを更新しました

于 2013-07-04T14:26:21.600 に答える
1

これが私が持ってきた解決策です:

var shiftRange = function (array, pos, amount) {

  //First and last position cannot be modified
  if (pos === 0 || pos === array.length-1) return;

  //Generate new array
  var newArray = array.slice();

  var max = array.length;

  //Calculate the modification ratio of the ranges
  var diference = newArray[max - 1] - newArray[pos];
  var newDiference = diference - amount;
  if (newDiference < 0) {
    newDiference = 0;
  }
  var modificationRatio = newDiference / diference;

  //Calculate the range with the previous item
  var ranges = [0];
  var old = null;
  newArray.forEach(function (item) {
    if (old !== null) {
      ranges.push(item - old);
    }
    old = item;

  });

  //Apply the amount
  newArray[pos] =  newArray[max-1] - newDiference;

  //Apply the ratio
  var aux;
  pos++;
  for (; pos < max - 1; pos++) {
    //get pre-increase range
    aux = ranges[pos];
    //calculate new range
    aux = aux * modificationRatio;
    //aply new range to previous value
    newArray[pos] = newArray[pos - 1] + aux;
  }
  return newArray;
};

//examples
var arr = [1,2,4,6,7,8];
alert(shiftRange(arr, 1, 1));
//1,3,4.666666666666667,6.333333333333334,7.166666666666667,8

arr = [0, 1, 2, 4, 5, 6];
alert(shiftRange(arr, 2, 1));
//0,1,3,4.5,5.25,6

arr = [-1, -0.2, 0.5, 0.6, 0.7, 1];
alert(shiftRange(arr, 1, 0.4));
//-1,0.20000000000000007,0.6666666666666667,0.7333333333333334,0.8,1

そして、ここにjsfidleがあります

于 2013-07-04T14:46:22.617 に答える