1

I have an array like below

const num = [1,2,3,4,5,6,7];

and boundary condition values,

var first = 6
var second = 3

Expected Output now based on this is like below,

[6,7,1,2,3]

Explain:

The result should combine 2 arrays:

  1. >= first in the left [6, 7]
  2. <= second in the right [1,2,3]

I tried trying something like below but array positions are not as I mentioned above.

const result = num.filter((n,p) => {
  if(p >= num.indexOf(first)) {return n}
  else if(p <= num.indexOf(second)) {return n}
});


console.log(result) // [1,2,3,6,7]

an alternative way is below but that is not efficient as I need to loop twice.

const num = [1,2,3,4,5,6,7];
var first = 6
var second = 3
var arr = []
num.forEach((n,p) => {
  if(p >= num.indexOf(first)) {arr.push(n)}
});
num.forEach((n,p) => {
  if(p <= num.indexOf(second)) {arr.push(n)}
});

console.log(arr) //[6,7,1,2,3]

Any better way to achieve this?

Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
Vikas Acharya
  • 3,550
  • 4
  • 19
  • 52
  • What is the expected output if the first and second boundary conditions are swapped around? – Terry Apr 07 '21 at 06:05
  • @Terry Don't worry Terry I already handled that situation. But, here am looking for a better way without doing the filter twice. – Vikas Acharya Apr 07 '21 at 06:12
  • 1
    I ran your second snippet with `first` and `second` swapped and got the output `[3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6]`. You need to properly say the condition based upon which you want the array. – Tsubasa Apr 07 '21 at 06:18
  • I've just mentioned the condition in my [answer below](https://stackoverflow.com/a/66980384/9071943). You can take a look at it @Xua & Terry – Nguyễn Văn Phong Apr 07 '21 at 06:34
  • 1
    That's cool! .... – Vikas Acharya Apr 07 '21 at 06:40
  • Is it possible for first to be smaller than second? – adiga Apr 07 '21 at 07:05
  • Yes, You can check the OP's explanation [here](https://stackoverflow.com/questions/66980182/how-to-filter-array-from-two-values-as-boundary-condition/66980384?noredirect=1#comment118396720_66980182) @adiga – Nguyễn Văn Phong Apr 07 '21 at 07:09

5 Answers5

2
var num = [1, 2, 3, 4, 5, 6, 7];
var first = 6;
var second = 3;
const res = [
  ...num.filter((n) => n >= first),
  ...num.filter((n) => n <= second)
];
console.log(res); // [6,7,1,2,3]

Update:

loop once:

var num = [1, 2, 3, 4, 5, 6, 7];
var first = 6;
var second = 3;
var left = [];
var right = [];
num.forEach((n) => {
  if (n >= first) left.push(n);
  if (n <= second) right.push(n);
});
const res = [...left, ...right];
console.log(res); // [6,7,1,2,3]
Yu Miao
  • 437
  • 2
  • 8
2

Your request seems special, to say the least, but the following should do the job:

const arr=[1,2,3,4,5,6,7];

// looking at positions of elements:
const getSubArraysPos=(ar,m,n)=>[...ar,...ar].slice(m-1,ar.length+n);
console.log(getSubArraysPos(arr,6,3))

// looking at array values:
const getSubArraysVal=(ar,m,n)=>[].concat.call(...ar.reduce((a,c)=>{
  if (m>n) { if(c>=m) a[0].push(c); else if (c<=n) a[1].push(c); }
  else if(c>=m && c<=n) a[0].push(c);
  return a }, [[],[]]));
  
console.log("6,3:",getSubArraysPos(arr,6,3));
console.log("5,2:",getSubArraysVal(arr,5,2));
console.log("2,5:",getSubArraysVal(arr,2,5))

The code is probably a bit "terse", but I was just trying to make it as "one-line" as possible.

Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
1

Firstly, I want to clarify the requirement, the result should combine 2 arrays:

  1. >= first in the left [6, 7]
  2. <= second in the right [1,2,3]

Output:1 & 2 = [6,7,1,2,3]


Solution:

The easy way is to use Array#reduce with initializing result as an object like this {first:[], second: []}. After that, use spread to concatenate 2 arrays.

As a result, you just need O(n) time complexity.

const num = [1,2,3,4,5,6,7];
var first = 6, second = 3;

const result = num.reduce((acc, curr) => {
  if(curr >= first) acc.first.push(curr);
  if(curr <= second) acc.second.push(curr);
  
  return acc;
}, {first:[], second: []});
console.log([...result.first, ...result.second]);
Nguyễn Văn Phong
  • 13,506
  • 17
  • 39
  • 56
1

Your initial solution with .filter mostly works, but .filter can't reorder an array.

Find the index of the first value. Use it to slice off the end of the array. Find the second value. Use it to slice off the beginning of the array. Join the two pieces.

const secondIdx = num.indexOf(second);
const firstIdx = num.indexOf(first, second+1);
const results = num.slice(firstIdx).concat(num.slice(0, secondIdx+1));
Ouroborus
  • 16,237
  • 4
  • 39
  • 62
0

I'm posting my own answer as above answers have some or other problem

function arr(num, first, second){
 let arr = num.reduce((acc, v, i) => {
  let i1 = num.indexOf(first)
  let i2 = num.indexOf(second)
  if(i1 < i2 && i >= i1 && i <= i2) acc['a'].push(v)
  if(i1 > i2 && i <= i2){
    acc['t1'].push(v) 
  } 
  if(i1 > i2 && i >= i1) {
    acc['t2'].push(v) 
  }
  if(i1 > i2) acc['a'] = [...acc['t2'], ...acc['t1']]
  return acc
}, {a : [], t1: [], t2: []})

return arr['a']
}

let num = [1,2,3,4,5,6,7];
console.log(arr(num,2,5))
console.log(arr(num,5,2))
console.log(arr(num,3,6))
console.log(arr(num,6,3))
Vikas Acharya
  • 3,550
  • 4
  • 19
  • 52