5

真ん中のアウトワードから配列を調べる必要があります。

var array = [a,b,c,d,e];

次の順序で印刷する必要があります:c、d、b、e、a

私はすでにアレイを半分に分割しました。最初に前進し、次に後退します。これはすでに改善されていますが、実際には、各サイドのアレイの最後まで、各サイドに1つずつ移動する必要があります。

真ん中から始めたいとしましょう。ループステートメント、条件の前に次のものがありますが、各側で段階的に切り替える3番目の部分を理解できないようです。

for (var i = Math.floor(array.length/2); i >= 0 || i < array.length; i?){
//Do Something here.
}

誰かがこれを行う方法を知っていますか?明らかに、私はこの状態でこれをテストすることができないようです。

ありがとう

私はこの関数を思い付くために以下の答えを修正しました(どうもありがとう)。アレイ内のどこからでも開始して、進む方向を選択できます。もっとエレガントに書けると思います。間違ったインデックス番号に対する安全性もあります。

var array = ["a", "b", "c", "d", "e"];

function processArrayMiddleOut(array, startIndex, direction){
    if (startIndex < 0){ 
        startIndex = 0;
    }
    else if ( startIndex > array.length){
        startIndex = array.lenght-1;
    };

    var newArray = [];

    var i = startIndex;

    if (direction === 'right'){
        var j = i +1;
        while (j < array.length || i >= 0 ){
            if (i >= 0) newArray.push(array[i]);
            if (j < array.length) newArray.push(array[j]);
            i--;
            j++;                
        };
    }
    else if(direction === 'left'){
        var j = i - 1;
        while (j >= 0 || i < array.length ){
            if (i < array.length) newArray.push(array[i]);
            if (j >= 0) newArray.push(array[j]);
            i++;
            j--;                
        };
    };

    return newArray;            
}    

var result = processArrayMiddleOut(array, 2, 'left');

alert(result.toString());

http://jsfiddle.net/amigoni/cqCuZ/

4

7 に答える 7

9

2つのカウンター、1つは上昇、もう1つは下降:

var array = ["a", "b", "c", "d", "e"];
var newArray = [];

var i = Math.ceil(array.length/2);
var j = i - 1;

while (j >= 0)
{
    newArray.push(array[j--]);
    if (i < array.length) newArray.push(array[i++]);
}

http://jsfiddle.net/X9cQL/

于 2012-10-17T15:56:45.467 に答える
3

それで、私はこれを再考することに決めました、私が与えた最初の答えにあまり満足していませんでした。データが正常に並べ替えられた場合、インデックス番号間に何らかの関係があると確信していました。最後のアイテム位置に反復番号を追加すると、そのパターンが見つかりました。

最初の配列には、以下を使用します['a', 'b', 'c', 'd', 'e']

開始点は、であり、配列値に対応するMath.floor( arr.length / 2 )を与えます。これは反復中です。次の手順では、値の数が奇数の配列をウォークスルーする方法について詳しく説明します。2c0

 Position | Direction | Iteration | New Position | Value at Position
----------+-----------+-----------+--------------+-------------------
     2    |      -    |      0    |       2      |         c
     2    |      +    |      1    |       3      |         d
     3    |      -    |      2    |       1      |         b
     1    |      +    |      3    |       4      |         e
     4    |      -    |      4    |       0      |         a

パターンが発達しているのがわかります。反復が奇妙な場合は、それを場所に追加して新しい位置を見つけます。反復が負の場合、位置からそれを減算して、新しい場所を見つけます。

偶数の値を持つ配列を処理する場合、ルールが反転します。値の数が偶数の場合、場所から奇数の反復を減算して新しい位置を取得し、場所に偶数の反復を追加して次の値を見つけます。

このソートロジックを実行するために必要なコードがどれだけ少ないかを示すために、上記のロジックの縮小バージョンを以下に示します(前述のリンクの方がはるかに読みやすくなっています)。

// DON'T USE THIS IN PRODUCTION, OR YOUR TEAM MAY KILL YOU
function gut(a){
    var o=[],s=a.length,l=Math.floor(s/2),c;
    for(c=0;c<s;c++)o.push(a[l+=(s%2?c%2?+c:-c:c%2?-c:+c)]);
    return o
}

上記のロジックをより読みやすい方法で実装します。

// Sort array from inside-out [a,b,c,d,e] -> [c,d,b,e,a]
function gut( arr ) {

    // Resulting array, Counting variable, Number of items, initial Location
    var out = [], cnt, 
        num = arr.length, 
        loc = Math.floor( num / 2 );

    // Cycle through as many times as the array is long
    for ( cnt = 0; cnt < num; cnt++ )
        // Protecting our cnt variable
        (function(){
            // If our array has an odd number of entries
            if ( num % 2 ) {
                // If on an odd iteration
                if ( cnt % 2 ) {
                    // Move location forward
                    loc = loc + (+cnt); 
                } else {
                    // Move location backwards
                    loc = loc + (-cnt);  
                }
            // Our array has an even number of entries
            } else {
                // If on an odd iteration
                if ( cnt % 2 ) {
                    // Move location backwards
                    loc = loc + (-cnt);
                } else {
                    // Move location forwards
                    loc = loc + (+cnt);
                }
            }
            // Push val at location to new array
            out.push( arr[ loc ] );
        })()

    // Return new array
    return out;

}
于 2012-10-17T15:23:48.947 に答える
1

さて、この問題を段階的に解決しましょう:

  1. 配列には、奇数または偶数の要素が含まれる場合があります。
  2. 配列に奇数の要素がある場合:
    1. 真ん中の要素はインデックスにあります(array.length - 1) / 2。このインデックスをと呼びmidます。
    2. mid中央の要素の左側にいくつかの要素があります。明らかに。
    3. mid真ん中の要素の右側にいくつかの要素があります。
  3. 配列に偶数の要素がある場合:
    1. 真ん中の要素はインデックスにありますarray.length / 2。このインデックスをと呼びmidます。
    2. mid中央の要素の左側にいくつかの要素があります。明らかに。
    3. mid - 1真ん中の要素の右側にいくつかの要素があります。

次に、上記の既知のデータを使用して、この問題に取り組む関数を作成しましょう。

function processMidOut(array, callback) {
    var length = array.length;
    var odd = length % 2;         // odd is 0 for an even number, 1 for odd
    var mid = (length - odd) / 2; // succinct, isn't it?

    callback(array[mid]);         // process the middle element first

    for (var i = 1; i <= mid; i++) {  // process mid number of elements
        if (odd || i < mid)           // process one less element if even
            callback(array[mid + i]); // process the right side element first
        callback(array[mid - i]);     // process the left side element next
    }
}

それがすべてです。それでは、いくつかの配列を作成して、それらを途中で処理してみましょう。

var odd = ["a", "b", "c", "d", "e"];
var even = ["a", "b", "c", "d", "e", "f"];

var oddOrder = "";
var evenOrder = "";

processMidOut(odd, function (element) {
    oddOrder += element;
});

processMidOut(even, function (element) {
    evenOrder += element;
});

alert(oddOrder);
alert(evenOrder);

ここで実用的なデモを見つけることができます:http://jsfiddle.net/xy267/1/

于 2012-10-17T16:31:12.890 に答える
1

非常に興味深いアルゴリズム。これが私が持ってきたものです:

walkMidleOut = function(arr, callback) {
    var mid = (arr.length - arr.length % 2) / 2;
    for (var i = 0; i < arr.length; i++) {
        var s = -1,
            j = (i % 2 ? (s = 1, i + 1) : i) / 2,
            index = mid + s * j == arr.length ? 0 : mid + s * j;
        callback.call(arr, arr[index], index);
    }
}

使用法:

walkMidleOut([1,2,3,4,5], function(el, index) {
    console.log(el, index);
});

あなたに与えるでしょう:

3 2
4 3
2 1
5 4
1 0

関数は、奇数または偶数の任意の数の要素で使用できます。

于 2012-10-17T17:29:33.433 に答える
1

とを使っconcat()slice()みませんか?これを真ん中の要素のインデックスに渡すことができます。

Array.prototype.eachFrom = function(index){
  var index = index > this.length ? 0 : index;
  return [].concat(this.slice(index), this.slice(0, index));
}

たとえば、次のようになります。

var arr = ['a', 'b', 'c', 'd', 'e'], arr = arr.eachFrom(2);
for( var i = 0; i < arr.length; i++ ) { doFunThings(); }
于 2013-03-15T05:04:07.267 に答える
0

アンダースコアと_(Object).Sort_Inside_Out()の使用:

_.mixin( {
    Sort_Inside_Out: function ( Object ) {
        Counter = 0
        return (
                _( Object ).sortBy( function ( Element ) {
                    Counter =
                            -Counter + (
                            ( Math.sign( Counter ) == 1 ) ?
                                    0 :
                                    1 )
                    return ( Counter )
                } ) )
    },
} )
于 2017-01-27T06:15:26.037 に答える
0

これは、配列内の任意のインデックスから開始し、同時に前方と後方の両方をループする簡単な方法です(つまり、インデックスに最も近いアイテムから始まり、遠くに移動するすべてのアイテムを反復処理します)。

let passing = 0;
function bothSides(arr, idx) {
    newArr = [];
    const shortLen = Math.min(idx, arr.length - idx);
    for (let i = 0; i < shortLen; i++) {
        newArr.push(arr[idx + i]); // add next
        newArr.push(arr[idx - i - 1]); // add previous
    }
    for (let i = idx + shortLen; i < arr.length; i++) {
        newArr.push(arr[i]); // add any remaining on right
    }
    for (let i = idx - shortLen - 1; i > -1; i--) {
        newArr.push(arr[i]); // add any remaining on left
    }
    return newArr;
}
var arr = [...Array(10).keys()]; // 0,1,2,3,4,5,6,7,8,9
passing += bothSides(arr, 0) == '0,1,2,3,4,5,6,7,8,9' ? 1 : 0;
passing += bothSides(arr, 2) == '2,1,3,0,4,5,6,7,8,9' ? 1 : 0;
passing += bothSides(arr, 4) == '4,3,5,2,6,1,7,0,8,9' ? 1 : 0;
passing += bothSides(arr, 5) == '5,4,6,3,7,2,8,1,9,0' ? 1 : 0;
passing += bothSides(arr, 7) == '7,6,8,5,9,4,3,2,1,0' ? 1 : 0;
passing += bothSides(arr, 9) == '9,8,7,6,5,4,3,2,1,0' ? 1 : 0;

// same algorigthm but as generator
function* bothSidesG(arr, idx) {
    const shortLen = Math.min(idx, arr.length - idx);
    for (let i = 0; i < shortLen; i++) {
        yield arr[idx + i]; // add next
        yield arr[idx - i - 1]; // add previous
    }
    for (let i = idx + shortLen; i < arr.length; i++) {
        yield arr[i]; // add any remaining on right
    }
    for (let i = idx - shortLen - 1; i > -1; i--) {
        yield arr[i]; // add any remaining on left
    }
}
var arr2 = [...Array(7).keys()]; // 0,1,2,3,4,5,6
passing += [...bothSidesG(arr2, 0)] == '0,1,2,3,4,5,6' ? 1 : 0;
passing += [...bothSidesG(arr2, 1)] == '1,0,2,3,4,5,6' ? 1 : 0;
passing += [...bothSidesG(arr2, 3)] == '3,2,4,1,5,0,6' ? 1 : 0;
passing += [...bothSidesG(arr2, 5)] == '5,4,6,3,2,1,0' ? 1 : 0;
passing += [...bothSidesG(arr2, 6)] == '6,5,4,3,2,1,0' ? 1 : 0;
console.log(`Passing ${passing} of 11 tests`);

于 2020-10-09T18:18:30.180 に答える