5

我需要从中间的外语中遍历一个数组。

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

我需要按以下顺序打印:c,d,b,e,a

我已经将阵列分成两半,先前进后退,这已经是一种改进,但我真的需要在每一侧各一个,直到每一侧阵列的末尾。

说我想从中间开始。我在循环语句之前有以下内容,条件,我似乎无法弄清楚第三部分以增量方式在每一侧切换一个。

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

两个计数器,一个上升,另一个下降:

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 ),它给了我们2,对应c于数组中的值。这是在迭代0中。以下说明详细说明了我们如何遍历具有奇数个值的数组:

 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

非常有趣的算法。这是我带来的:

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

好的,让我们一步一步解决这个问题:

  1. 数组可能有奇数或偶数个元素:
  2. 如果数组有奇数个元素:
    1. 中间元素位于 index 处(array.length - 1) / 2。让这个索引被称为mid
    2. mid中间元素左侧有多个元素。明显地。
    3. mid中间元素右侧有许多元素。
  3. 如果数组有偶数个元素:
    1. 中间元素位于 index 处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

使用concat()and怎么样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

这是一种从数组中的任何索引开始并同时向前和向后循环的简单方法(即,从最接近索引的项目开始迭代所有项目并移动得更远)。

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 回答
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 回答