从中间处理数组

时间:2012-10-17 15:21:30

标签: javascript arrays

我需要从中间词语中查看数组。

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.
}

有谁知道怎么做? 显然我似乎无法在这种情况下测试这一点。

由于

我修改了the answer below(非常感谢)来提出这个功能。它允许从阵列中的任何位置开始并选择要去的方向。我相信它可以写得更优雅。错误的索引号也有安全性。

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/

7 个答案:

答案 0 :(得分:8)

两个柜台,一个上升,另一个上下:

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/

答案 1 :(得分:2)

所以我决定重温这一点,对我给出的第一个答案并不满意。我很肯定当数据成功重新排序时,索引号之间会有一些关系;我在最后一个项目位置添加了迭代编号的模式。

对于我们的初始数组,我们将使用以下内容:['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;

}

答案 2 :(得分:1)

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

  1. 数组可能包含奇数或偶数元素:
  2. 如果数组有奇数个元素:
    1. 中间元素位于索引(array.length - 1) / 2。将此索引称为mid
    2. 中间元素左侧有mid个元素。明显。
    3. 中间元素右侧有mid个元素。
  3. 如果数组具有偶数个元素:
    1. 中间元素位于索引array.length / 2。将此索引称为mid
    2. 中间元素左侧有mid个元素。明显。
    3. 中间元素右侧有mid - 1个元素。
  4. 现在让我们使用上述已知数据创建一个解决此问题的函数:

    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/

答案 3 :(得分: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

函数可以与任意数量的元素一起使用,奇数或偶数。

答案 4 :(得分: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(); }

答案 5 :(得分:0)

使用underscore和_(对象).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 )
                } ) )
    },
} )

答案 6 :(得分: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`);