Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

With a lack of math neurons in my brain, i struggle a bit in finding my way around this.

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

  • A one-dimensional, normal indexed Array with X elements (the values being unique IDs)
  • A target ID to select
  • An amount of elements to return

The third parameter would ask the function to return a set of elements, with the element having the target ID being either in the center of the result, or next to it.

The result of the function should be an array as well.

A few examples to make it a more visual explanation:

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 while writing the code, which i am currently attempting to, but i find myself writing strange conditions, numerous if-statements and code that generally seems like a work-around. Also the cases of parameter 3 being larger than the amount of elements in parameter 1 are a bit of an over-brainer for me.

I feel unsafe continuing with this code, because it feels buggy and simply not proper. Surely somebody with proper math skills could provide me with the theory i need to understand how to accomplish this in a more elegant fashion.

Theory or pseudo-code will suffice, but if someone has something like this ready at hand, please don't hesitate to share it.

Thank You!

(Here is what i have written so far - based on the prototype JS class 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: In order to make this more understandable i will state the purpose. This code is supposed to be used for kind of a slideshow, in which multiple elements (parameter 3) are visible at the same time. Parameter 1 is the list of (the IDs of the) total elements in their correct order as they appear in the HTML declaration. Parameter 2 is the element that is currently selected and therefore should appear in the middle.

like image 662
SquareCat Avatar asked Jan 21 '26 02:01

SquareCat


1 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]
like image 174
VisioN Avatar answered Jan 23 '26 15:01

VisioN