Selecting a set of elements from a simple one-dimensional array with a target element in the middle

With the lack of math neurons in my brain, I struggle a bit to find a way to get around this.

I need to create a simple javascript function that will receive three parameters:

  • One dimensional normal indexed array with X elements (values ​​are unique identifiers)
  • Target ID for selection
  • Number of items to return

The third parameter will ask the function to return a set of items, with the item having the target ID either in the center of the result or near it.

The result of the function must be an array.

A few examples to make it clearer:

function([100,120,140,160,180,200], 120, 3)
// should return [100,120,140]

function([100,120,140,160,180,200], 160, 4)
// should return [140,160,180,200]

function([100,120,140,160,180,200], 180, 5)
// should return [140,160,180,200,100]

      

The case covered by the last example is what confuses me when writing the code I'm currently trying to do, but I find myself in writing strange conditions, numerous if statements, and code that usually seem like workarounds. Also, cases where parameter 3 is greater than the number of items in parameter 1 is a little more difficult for me.

I feel insecure going on with this code because it feels buggy and just doesn't fit. Surely someone with proper math skills could give me the theory, I have to figure out how to do it more elegantly.

Theory or pseudocode will suffice, but if anyone has something like this on hand, please feel free to share it.

Thank!

(This is what I have written so far - based on the JS class prototype implementation)

var CBasicMatrix=Class.create({

    initialize: function(elementList){
        this.elementList=elementList;
    },

    select: function(id, amount){
        if(amount>this.elementList.length) 
            amount=this.elementList.length;
        if(!this.elementList.length) return false;
        var elementIndex=this.elementList.indexOf(id);
        if(elementIndex==-1) return false;
        var isRound=amount%2==0;
        var amountHalf=isRound ? (amount/2) : (Math.ceil(amount/2)-1);
        // [464,460,462,461,463]
        var result=[];
        if(elementIndex-amountHalf >= 0) {
            var startIndex=(elementIndex-amountHalf);
            for(i=startIndex;i<=startIndex+amount;i++){
                result.push(this.elementList[i];
            }
        } else {
            // more seemingly stupid iterative code coming here 
        }

    }

});

      

Edit: To make it clearer, I'll give the purpose. This code is supposed to be used for a kind of slideshow in which several elements are displayed at the same time (parameter 3). Parameter 1 is a list (of ids) of all elements in their correct order as they appear in the HTML declaration. Parameter 2 is the item that is currently selected and therefore should appear in the middle.

+3


source to share


3 answers


Here is my solution:

function method(arr, value, n) {
    var result = [],
        len = arr.length,
        index = arr.indexOf(value);

    for (var i = 0; index > -1 && i < n ; i++) {
        result.push(arr[(len + index - ~~(n / 2) + (n % 2 ^ 1) + i) % len]);
    }

    return result;
}

      



TESTS:

var arr = [100, 120, 140, 160, 180, 200];

method(arr, 120, 3);  // [100, 120, 140]
method(arr, 160, 4);  // [140, 160, 180, 200]
method(arr, 180, 5);  // [140, 160, 180, 200, 100]
method(arr, 100, 3);  // [200, 100, 120]

      

+2


source


I'll help you by providing pseudo code:

1.if there is no match you should return an empty array.

2.if there is a match, you just divide the third parameter by 2, you take the result, you loop over the found element, minus the previous result, up to the third parameter value, and store the elements in a new array.



3.you are returning a new array.

Update: I saw your code and I don't see any problem with it.

0


source


After some careful debugging and reevaluation of my approach, I was able to find a solution that seems correct and safe. I'm sure this can be optimized further and if anyone has any suggestions feel free to share them.

var CBasicMatrix=Class.create({

    initialize: function(elementList){
        this.elementList=elementList;
    },

    select: function(id, amount){
        if(amount>this.elementList.length) 
            amount=this.elementList.length;
        if(!this.elementList.length) return false;
        var elementIndex=this.elementList.indexOf(id);
        if(elementIndex==-1) return false;
        var isRound=amount%2==0;
        var amountHalf=isRound ? (amount/2) : (Math.floor(amount/2));
        var result=[];
        var startIndex=(elementIndex-amountHalf);
        var endIndex=(startIndex+amount-1);
        var targetIndex=0;
        for(i=startIndex;i<=endIndex;i++){
            targetIndex=i;
            if(i>this.elementList.length-1) targetIndex=i-this.elementList.length;
            if(i<0) targetIndex=i+this.elementList.length;
            result.push(this.elementList[targetIndex]);
        }
        return result;
    }

});

      

0


source







All Articles