Related
The question seems to be a bit weird. Never mind.
This is an array
[2, 7, 5, 10]
If I want to get the next greater number after 2, here's my code
var MyArray = [2, 7, 5, 10];
var RandomNumber = 2;
var MinGreaterThanPos;
for (var i =0; i < MyArray.length; i++) {
if (MyArray[i] <= RandomNumber)
continue;
if (typeof(MinGreaterThanPos) == 'undefined' || MyArray[i] < MinGreaterThanPos)
{
MinGreaterThanPos = i;
}
}
alert(MyArray[MinGreaterThanPos]);
It will return 7.
What if I want to get the lowest among the greater numbers after 2?
That means, 7, 5, 10 are greater than 2. But I want to get 5, since the difference between 5 and 2 is lesser than any of the rest comparing with 2.
How will I do that?
Updated:
Coming to this point so far, what if there are objects inside an array?
For example:
var MyArray = [{user: 1, position:2}, {user:2, position: 6}, {user:3, position: 4}];
I want to do the same thing only with position. If I choose position 2, then the next position I am hoping to get back is 4 and not 6.
Another way to solve your problem is the following. Initially, we extend the Array adding a min method, in order we get the minimum element of an array. This is taken from here. Then we filter our array, in order we exlcude the enries that are less or equal to the number we hava as a threshold. Last we find the min number.
Array.min = function( array ){
return Math.min.apply( Math, array );
};
var numbers = [2, 7, 5, 10];
var number = 5;
var numbers = numbers.filter( function( n ){
return n > number;
});
console.log( Array.min( numbers ) );
first you sort the array then you get next of last item equal to RandomNumber if there is duplicates
var MyArray = [2,2,2, 10, 7, 5,5,7,5];//to test duplicates
var RandomNumber = 2;
var srt = MyArray.sort(function(a,b){return a-b});
var MinGreaterThanPos = srt[srt.lastIndexOf(RandomNumber)+1];
alert(MinGreaterThanPos);
This returns the minimal of array elements greater than el:
function minNext (a, el) {
var min = Infinity;
for (let x of a) {
if (x > el && x - el < min - el)
min = x;
}
return min;
}
//
let a = [1,9,2,8,3,-2,7,4,-3,6,5,5,5];
for (let x of a)
console.log(x, minNext(a, x))
less efficient, but more idiomatic:
let minNext = (a, el) => Math.min.apply(0, a.filter(x => x > el));
you can use this
var ar = [2,7,5,10];
Math.min.apply(undefined, ar.filter(function(x,y){return y > 0}));
//for any explanation, tell it in comment
You might do like this in a single pass. It takes into account the duplicates as well;
var arr = [2, 7, 5, 2, 10],
result = arr.reduce((p,c) => c < p[0] ? (p[0] = c,p)
: c < p[1] ? (p[0] !== c && (p[1] = c),p)
: p, [Infinity,Infinity])[1];
console.log(result);
As per objects as array items you simply the modify the code to show as follows;
var arr = [{user: 1, pos:2}, {user:2, pos: 6}, {user:3, pos: 4}, {user:4, pos: 12}, {user:5, pos: 9}],
result = arr.reduce((p,c) => c.pos < p[0].pos ? (p[0] = c,p)
: c.pos < p[1].pos ? (p[0].pos !== c.pos && (p[1] = c),p)
: p, [{pos:Infinity},{pos:Infinity}])[1];
console.log(result);
You can first sort and then loop through the array and until you find the next larger value. This way you will always have the second lowest value even if you have multiple.
var MyArray = [2,7,5,10];
var RandomNumber = 2;
var MinGreaterThanPos;
sortedMyArray = MyArray.sort(function(a, b){return a-b});
for(var i in sortedMyArray) {
if (sortedMyArray[i] > RandomNumber) {
MinGreaterThanPos = i;
break;
}
}
alert(sortedMyArray[MinGreaterThanPos]);
You can do the same for position as:
var MyArray = [{user: 1, position:2}, {user:2, position: 6}, {user:3, position: 4}];
var RandomNumber = 2;
var MinGreaterThanPos;
sortedMyArray = MyArray.sort(function(a, b){return a.position-b.position});
for(var i in sortedMyArray) {
if (sortedMyArray[i].position > RandomNumber) {
MinGreaterThanPos = i;
break;
}
};
alert(sortedMyArray[MinGreaterThanPos]);
And if your don't want to use RandomNumber
var MyArray = [{user: 1, position:2}, {user:2, position: 6}, {user:3, position: 4}];
var MinGreaterThanPos;
sortedMyArray = MyArray.sort(function(a, b){return a.position-b.position});
for(var i in sortedMyArray) {
if (sortedMyArray[i].position > sortedMyArray[0].position) {
MinGreaterThanPos = i;
break;
}
};
alert(sortedMyArray[MinGreaterThanPos]);
You could use Array#reduce.
function getItem(array, search) {
return array.reduce(function (r, a) {
return a.position > search && (!r || r.position > a.position) ? a : r;
}, undefined);
}
var array1 = [{ user: 1, position: 2 }, { user: 2, position: 6 }, { user: 3, position: 4 }],
array2 = [{ user: 1, position: 2 }, { user: 2, position: 6 }, { user: 3, position: 4 }, { user: 4, position: 5 }];
console.log(getItem(array1, 2));
console.log(getItem(array2, 2));
That's right. Unlike most questions, I am not trying to write a regular expression myself. I am trying to generate a regular expression (JavaScript flavoured, to be used in HTML5's pattern attribute).
Given an array of numbers, give a concise, fast, and correct regular expression that will only match the given input. I have already done part of the job, namely the ones [0-9]:
var ones = [0, 1, 2, 3, 4, 5, 8, 9],
onesRegex = "";
for (var i = 0; i < ones.length; i++) {
e = ones[i];
if (i > 0 && e == ones[i - 1] + 1) {
if (i != ones[i + 1] - 1) {
onesRegex += e + "]";
}
} else {
if (onesRegex != "") onesRegex += "|";
onesRegex += "[" + e + "-";
}
}
// Returns [0-5]|[8-9]
alert(onesRegex);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
This could then be used in an <input> (yes, jQuery is allowed):
$("input").attr("pattern", onesRegex);
The problem I am experiencing is that I am not sure how to continue. Ones are easy enough, as you see above. However, things get increasingly more difficult as soon as you start adding digits because you have to take into account so many things. For instance, you can have [112, 358, 359, 360, 361] which should result in (112|(3(5[8-9]|6[0-1]))) which is already quite extensive for only five numbers.
For my project, the maximum value is 500, so all values < 1000 should be parsable.
I have written quite a bit, but there's a lot to be done -- I need to get the logic behind it. So far my idea is to split the number in ones, tens, and hundreds, and treat them accordingly. Additionally, the appropriate function can waterfall down to other functions. For instance, parsing the number 512 could split it down into 5 and 12, 12 will go down to a function for decimals, and so on. That's the main idea, but the logic and structure is missing.
Here is what I have so far, but I also provide a JSFiddle which is a bit easier to work with.
var arr = [0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 105, 106, 107, 256, 257, 258, 259, 260],
onesArray = [],
tensArray = [],
hundredsArray = [];
// MAIN
function regexGenerator() {
orderSplitter(arr);
// Do stuff
// Should return finished Regex as a string
}
// Split input array in ones (1 digit), tens (2 digits), hundreds (3 digits)
function orderSplitter(numberArray) {
$(numberArray).each(function(index, element) {
if (element < 10) {
onesArray.push(element);
} else if (element < 100 && element > 9) {
tensArray.push(element);
} else if (element < 1000 && element > 99) {
hundredsArray.push(element);
}
});
}
/* Following functions expect an array as input */
function onesToRegex(ones) {
var onesRegex = "";
for (var i = 0; i < ones.length; i++) {
var e = ones[i];
if (i > 0 && e == ones[i - 1] + 1) {
if (i != ones[i + 1] - 1) {
onesRegex += e + "]";
}
} else {
onesRegex += "[" + e + "-";
}
}
return onesRegex;
}
function tensToRegex(tens) {
var tensRegex = "";
for (var j = 0; j < tens.length; j++) {
var f = tens[j],
ten = Math.floor(f / 10),
one = f - (ten * 10);
}
return tensRegex;
}
function hundredsToRegex(hundreds) {
var hundredsRegex = "";
for (var k = 0; k < hundreds.length; k++) {
var g = tens[j],
hundred = Math.floor(g / 100),
ten = Math.floor((g - (hundred * 100)) / 10),
one = g - (ten * 10);
}
return hundredsRegex;
}
As an alternative approach, consider using HTML5 <datalist>. This can be generated in JavaScript too.
var arr = [.......];
var datalist = document.createElement('datalist');
arr.forEach(function(num) {
var option = document.createElement('option');
option.value = num;
datalist.appendChild(option);
});
datalist.id = "numberlist";
document.body.appendChild(datalist);
// apply to input
someInputElement.setAttribute("list","numberlist");
Here's a demo for you: https://jsfiddle.net/960sjuhc/
A proposal with a tree.
Basically it has two parts
build tree with an object, where the length of the stringed numbers are the first key, and the rest are properties with one digit and an object.
build the regular expression string with iterating over the first key (the length) and start iter with the content of the property and the decremented length/depth of the following object.
function getRegex(array) {
function group(array) { // take array [0,1,3,4,5,6,8] return string '013-68'
return array.reduce(function (r, a, i, aa) {
if (!i || aa[i - 1] + 1 !== a) {
return r.concat([[a]]);
}
r[r.length - 1][1] = a;
return r;
}, []).map(function (a) {
return a.join(a[0] + 1 === a[1] ? '' : '-');
}).join('');
}
function iter(o, l) { // iterate an object
// get all keys form the object as sorted numbers
var keys = Object.keys(o).map(Number).sort(function (a, b) { return a - b; });
if (keys.length === 1) { // if just one key return the key and get the next level
return keys[0] + iter(o[keys[0]], l - 1);
}
if (keys.length > 1) { // if more than one key
// test the level
// if next level
// return parenthesis with all keys and their next levels separated with |
// if no level
// return grouped keys with brackets around
return l ?
'(' + keys.map(function (k) { return k + iter(o[k], l - 1); }).join('|') + ')' :
'[' + group(keys) + ']';
}
return '';
}
var tree = {};
array.forEach(function (a) {
var o, s = a.toString();
tree[s.length] = tree[s.length] || {};
o = tree[s.length];
s.split('').forEach(function (b) {
o[b] = o[b] || {};
o = o[b];
});
});
return '(' + Object.keys(tree).map(function (k) { return iter(tree[k], +k - 1); }).join('|') + ')';
}
document.write('<pre>' + getRegex([0, 1, 2, 3, 4, 5, 8, 9]) + '</pre>');
document.write('<pre>' + getRegex([100, 200, 212, 213, 214, 357]) + '</pre>');
document.write('<pre>' + getRegex([112, 358, 359, 360, 361]) + '</pre>');
document.write('<pre>' + getRegex([0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 105, 106, 107, 256, 257, 258, 259, 260]) + '</pre>');
As was pointed out in the comments, I should have had some fun with it -- and I followed your advice and here we are! My solution is probably not as efficient as Nina Scholz's answer (not tested, but that answer just looks more... detailed) but it is better readable in my opinion and it was a lot of fun to make -- and not at all as hard as I had thought, once I got my head around it.
It's on JSFiddle. And also here as a snippet. I did my best commenting the some-what harder parts, but most of it should be quite straightforward, though in retrospect I could've chosen some better variable names. Comments are welcome!
var arr = [0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 105, 106, 107, 256, 257, 258, 259, 260],
onesArray = [],
tensArray = [],
tensMultiArray = {},
hundredsArray = [],
hundredsMultiArray = {};
// MAIN
function regexGenerator(arr) {
orderSplitter(arr);
var onesRegexString = onesToRegex(onesArray);
var tensRegexString = tensToRegex(tensArray);
var hundredsRegexString = hundredsToRegex(hundredsArray);
// Don't forget start/end points ^$
var regex = "(^(" + onesRegexString + ")$)|(^(" + tensRegexString + ")$)|(^(" + hundredsRegexString + ")$)";
$(".result code").text(regex);
}
regexGenerator(arr);
// Split input array in ones (1 digit), tens (2 digits), hundreds (3 digits)
// Can be extended to include others
function orderSplitter(numberArray) {
$(numberArray).each(function(index, element) {
if (element < 10) {
onesArray.push(element);
} else if (element < 100 && element > 9) {
tensArray.push(element);
} else if (element < 1000 && element > 99) {
hundredsArray.push(element);
}
});
}
/* Following functions expect an array as input */
function onesToRegex(ones) {
var onesRegex = "";
for (var i = 0; i < ones.length; i++) {
var e = ones[i];
// If this element is not the first element, and it is equal to
// the previous number + 1
if (i > 0 && e == (ones[i - 1] + 1)) {
// If this element is NOT equal to the next element - 1
// Will also return true if next item does not exist
if (e != (ones[i + 1] - 1)) {
onesRegex += e + "]";
}
}
// If this item is a (new) first item in a list
else {
if (onesRegex != "") onesRegex += "|";
onesRegex += "[" + e + "-";
}
}
return onesRegex;
}
function tensToRegex(tens) {
var tensRegex = "";
// Loop the array and break the number down in digits
// E.g. 13 -> ten = 1; one = 3
$(tens).each(function(index, element) {
var ten = Math.floor(element / 10),
one = element - (ten * 10);
// Push items to associative arrays (objects)
if (!(ten in tensMultiArray)) {
tensMultiArray[ten] = [one];
} else {
tensMultiArray[ten].push(one);
}
});
var i = 0;
for (var ten in tensMultiArray) {
if (tensMultiArray.hasOwnProperty(ten)) {
// Each iteration is a new number, meaning it is an *alternative*
// Hence the pipe
if (i > 0) tensRegex += "|";
tensRegex += ten;
// The `one` digits belonging to ten (e.g. 1 and 2 for 11 and 12) is an array
// Therefore we can send it down to onesToRegex to be processed
if (tensMultiArray[ten].length > 1) {
tensRegex += "(" + onesToRegex(tensMultiArray[ten]) + ")";
} else {
tensRegex += tensMultiArray[ten][0];
}
i++;
}
}
return tensRegex;
}
function hundredsToRegex(hundreds) {
var hundredsRegex = "";
// Loop the array and break the number down in hundreds and rest
// E.g. 128 -> hundred = 1; rest = 28
$(hundreds).each(function(index, element) {
var hundred = Math.floor(element / 100),
rest = element - (hundred * 100);
// Push items to associative arrays (objects)
if (!(hundred in hundredsMultiArray)) {
hundredsMultiArray[hundred] = [rest];
} else {
hundredsMultiArray[hundred].push(rest);
}
});
var i = 0;
for (var hundred in hundredsMultiArray) {
if (hundredsMultiArray.hasOwnProperty(hundred)) {
// Each iteration is a new number, meaning it is an *alternative*
// Hence the pipe
if (i > 0) hundredsRegex += "|";
hundredsRegex += hundred;
// The `rest` digits belonging to hundred (e.g. 28 and 29 for 128 and 129)
// is an array. Therefore we can send it down to tensToRegex to be processed
// In turn, tensToRegex will also send its ones through to onesToRegex
if (hundredsMultiArray[hundred].length > 1) {
hundredsRegex += "(" + tensToRegex(hundredsMultiArray[hundred]) + ")";
} else {
hundredsRegex += hundredsMultiArray[hundred][0];
}
i++;
}
}
return hundredsRegex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>
Generate Regular Expression based on an input array
</h1>
<p>
In this example the input is <code>[0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 20, 21, 105, 106, 107, 256, 257, 258, 259, 260]</code>. The result is:
</p>
<p class="result"><code></code></p>
Say I have a list [1,2,3,4,5,6,7]
and I would like to find the closest sum of numbers to a given number. Sorry for the crappy explanation but here's an example:
Say I have a list [1,2,3,4,5,6,7] I want to find the closest numbers to, say, 10.
Then the method should return 6 and 4 or 7 and 3 because its the closest he can get to 10. So 5 + 4 would be wrong because thats 9 and he can make a 10.
another example : you want the closest to 14 , so then he should return 7 and 6
If you got any questions plz ask because its difficult to explain what I want :P
Functions for combine, locationOf, are taken from different answers, written by different authors.
printClosest([0.5,2,4] , 5);
printClosest([1, 2, 3, 4, 5, 6, 7], 28);
printClosest([1, 2, 3, 4, 5, 6, 7], 10.9);
printClosest([1, 2, 3, 4, 5, 6, 7], 10, 2);
printClosest([1, 2, 3, 4, 5, 6, 7], 10, 3);
printClosest([1, 2, 3, 4, 5, 6, 7], 14, 2);
function printClosest(array, value, limit) {
var checkLength = function(array) {
return array.length === limit;
};
var combinations = combine(array); //get all combinations
combinations = limit ? combinations.filter(checkLength) : combinations;//limit length if required
var sum = combinations.map(function(c) { //create an array with sum of combinations
return c.reduce(function(p, c) {
return p + c;
}, 0)
});
var sumSorted = sum.slice(0).sort(function(a, b) {//sort sum array
return a - b;
});
index = locationOf(value, sumSorted);//find where the value fits in
//index = (Math.abs(value - sum[index]) <= Math.abs(value - sum[index + 1])) ? index : index + 1;
index = index >= sum.length ? sum.length - 1 : index;
index = sum.indexOf(sumSorted[index]);//get the respective combination
console.log(sum, combinations, index);
document.getElementById("result").innerHTML += "value : " + value + " combi: " + combinations[index].toString() + " (limit : " + (limit || "none") + ")<br>";
}
function combine(a) {
var fn = function(n, src, got, all) {
if (n == 0) {
if (got.length > 0) {
all[all.length] = got;
}
return;
}
for (var j = 0; j < src.length; j++) {
fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all);
}
return;
}
var all = [];
for (var i = 0; i < a.length; i++) {
fn(i, a, [], all);
}
all.push(a);
return all;
}
function locationOf(element, array, start, end) {
start = start || 0;
end = end || array.length;
var pivot = parseInt(start + (end - start) / 2, 10);
if (end - start <= 1 || array[pivot] === element) return pivot;
if (array[pivot] < element) {
return locationOf(element, array, pivot, end);
} else {
return locationOf(element, array, start, pivot);
}
}
<pre id="result"><pre>
var data= [1, 2, 3,4,5,6,7];
var closest = 14;
for (var x = 0; x < data.length; x++) {
for (var y = x+1; y < data.length; y++) {
if(data[x] + data[y] == closet){
alert(data[x].toString() + " " + data[y].toString());
}
}
}
From what I understood from your question, I made this snippet. I assumed you did not wanted to have the same digit twice (e.g 14 => 7 + 7).
It is working with your examples.
var arr = [1, 2, 3, 4, 5, 6, 7];
var a = 0, b = 0;
var nb = 14;
for(var i in arr) {
for(var j in arr) {
if(i != j) {
var tmp = arr[i] + arr[j];
if(tmp <= nb && tmp > a + b) {
a = arr[i];
b = arr[j];
}
}
}
}
document.write("Closest to " + nb + " => " + a + " + " + b);
I have a little bit long winded solution to the problem just so it is easier to see what is done.
The main benefits with solution below:
The second loop will not start from beginning of the array again. What I mean that instead of having loop_boundary for second loop as 0 as you normally would, here it starts from next index. This helps if your numbers array is long. However, if it as short as in example, the impact in performance is minimal. Decreasing first loop's boundary by one will prevent errors from happening.
Works even when the wanted number is 1 or negative numbers.
Fiddle:
JSFiddle
The code:
var numbers = [1,2,3,4,5,6,7];
var wanted_number = 1;
var closest_range, closest1, closest2 = null;
var loop1_boundary = numbers.length-1;
for(var i=0; i<loop1_boundary; i++) {
var start_index = i+1;
var loop2_boundary = numbers.length;
for(var k=start_index; k<loop2_boundary; k++) {
var number1 = parseInt(numbers[i]);
var number2 = parseInt(numbers[k]);
var sum = number1 + number2;
var range = wanted_number - sum;
document.write( number1+' + '+number2 +' < '+closest_range+'<br/>' );
if(Math.abs(range) < Math.abs(closest_range) || closest_range == null ) {
closest_range = range;
closest1 = number1;
closest2 = number2;
}
}
if(range==0){
break;
}
}
document.write( 'closest to given number was '+closest1+' and '+closest2+'. The range from wanted number is '+closest_range );
This proposal generates all possible combinations, collects them in an object which takes the sum as key and filters then the closest sum to the given value.
function getSum(array, sum) {
function add(a, b) { return a + b; }
function c(left, right) {
var s = right.reduce(add, 0);
if (s > sum) {
return;
}
if (!result.length || s === result[0].reduce(add, 0)) {
result.push(right);
} else if (s > result[0].reduce(add, 0)) {
result = [right];
}
left.forEach(function (a, i) {
var x = left.slice();
x.splice(i);
c(left.slice(0, i), [a].concat(right));
});
}
var result = [];
c(array, [], 0);
return result;
}
function print(o) {
document.write('<pre>' + JSON.stringify(o, 0, 4) + '</pre>');
}
print(getSum([1, 2, 3, 4, 5, 6, 7], 10));
print(getSum([1, 2, 3, 4, 5, 6, 7], 14));
print(getSum([1, 2, 3, 4, 5, 6, 7], 19));
I have an array e.g.
var arr = [2,7,3,8,9,4,9,2,8,7,9,7,3,2,4,5,7,8,2,7,6,1,8];
I want that (I think for-loop is best for this to loop over this) a for-loop loops over the whole array and gets 5 items near eachother in the array and runs a function with those 5 items to calculate an average of them. This has of course to repeat till there are no parts of 5 available. The array above has 23 values. So when I should run a code on it, it can loop 4 times on it, cos one more time can't cos it has 3/5 values.
I thought about doing:
for (var i = 0; i < arr.length; i++) {
doThisFunction(i, i+1, i+2, i+3, i+4 );
}
but that shouldn't be efficient I believe... any help?
You're on to something, the easy way to do it is
var arr = [2,7,3,8,9,4,9,2,8,7,9,7,3,2,4,5,7,8,2,7,6,1,8];
var result = [];
for (var i=0; (i+5)<arr.length; i=i+5) {
var average = (arr[i] + arr[i+1] + arr[i+2] + arr[i+3] + arr[i+4]) / 5;
result.push(average);
}
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 4) + '</pre>';
The somewhat fancier way to do the same thing
var result = arr.map(function(x,i) {
return i%5===0 ? arr.slice(i, i+5).reduce(function(a,b) {return a+b}) / 5 : NaN;
}).filter(isFinite);
Use array.slice:
for (var i = 0; i < Math.floor(arr.length/5); i++) {
f(arr.slice(i*5, i*5+5))
}
The following uses reduce and a slice to sum up a range of values from the array.
function averageRange(arr, start, end) {
return (function(range) {
return range.reduce(
function(total, val) {
return total + val;
}, 0) / range.length;
}([].slice.apply(arr, [].slice.call(arguments, 1))))
}
function averageEveryN(arr, n) {
return arr.map(function(_, index, arr) {
return index % n === 0 ? averageRange(arr, index, index + count) : NaN;
}).filter(isFinite).slice(0, Math.floor(arr.length / n));
}
function println(text) {
document.getElementsByTagName('body')[0].innerHTML += text + '<br />';
}
var arr = [2, 7, 3, 8, 9, 4, 9, 2, 8, 7, 9, 7, 3, 2, 4, 5, 7, 8, 2, 7, 6, 1, 8];
var count = 5;
averageEveryN(arr, count).map(function(value, index) {
println((index + 1) + '.) ' + value.toFixed(4));
});
Output
1.) 5.8000
2.) 6.0000
3.) 5.0000
4.) 5.8000
There is an array of numbers [1,2,3,4,5,6,7,8,9,10]
I need to get all numbers from this sequence that are different from current for more than 2 items, but looped.
For example if current number is one, so new list should have everything except 9,10,1,2,3, or if current number is four so new list should be everything except 2,3,4,5,6.
Is there any technique how to make this, without creating multiple loops for items at start and at the end?
Thank you.
var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var exclude = function (start, distance, array) {
var result = [];
for (var i = 0; i < array.length; i++) {
var d = Math.min(
Math.abs(start - i - 1),
Math.abs(array.length + start - i - 1)
)
if (d > distance) {
result.push(array[i]);
}
}
return result;
}
I think this performs what you asked:
// Sorry about the name
function strangePick(value, array) {
var n = array.length
, i = array.indexOf(value);
if (i >= 0) {
// Picked number
var result = [value];
// Previous 2 numbers
result.unshift(array[(i + n - 1) % n]);
result.unshift(array[(i + n - 2) % n]);
// Next 2 numbers
result.push(array[(i + 1) % n]);
result.push(array[(i + 2) % n]);
return result;
} else {
return [];
}
}
Some tests:
var array = [1,2,3,4,5,6,7,8,9,10];
console.log(strangePick(1, array)); // [9,10,1,2,3]
console.log(strangePick(4, array)); // [2,3,4,5,6]
You may use javascript array.slice:
function get_offset_sequence(arr, index, offset) {
var result = [];
if (index - offset < 0) {
result = arr.slice(index - offset).concat(arr.slice(0, index + offset + 1));
}
else if (index + offset > arr.length - 1) {
result = arr.slice(index - offset).concat(arr.slice(0, Math.abs(arr.length - 1 - index - offset)));
}
else {
result = arr.slice(index - offset, index + offset + 1)
}
return result;
}
Example of use:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var index = 1;
var offset = 2;
for (var i=0; i < 10; i++) { console.log(i, arr[i], get_offset_sequence(arr, i, offset)) }