9

Here's my code:

var myArr = [1,2,3,4,5];
function queue(arr, item) {
  return arr.push(item).shift();
}

I'm attempting to create a function queue which takes an "array" and an "item" as arguments. I need to

  1. Add the item onto the end of the array
  2. Remove the first element of the array
  3. Return the element that was removed.

My code is not working. Can you help me figure this out?

5 Answers 5

13

Just don't chain the method calls:

function queue(arr, item) {
  arr.push(item);
  return arr.shift();
}

Or, if you want a single statement,

function queue(arr, item) {
  return arr.push(item), arr.shift();
}

Alternatively, if you are mad enough, you could subclass Array and add a chainable push:

class MyArray extends Array {
  chainablePush(item) {
    this.push(item);
    return this;
  }
}
var myArr = new MyArray(1,2,3);
myArr.chainablePush(4).shift(); // 1
myArr; // MyArray [2,3,4];
Sign up to request clarification or add additional context in comments.

6 Comments

return arr.push(item), arr.shift(); Whoa! What's that? Is it returning a tuple like object, or just the last expression?
I think you should return the value returned when you shifted the array.
@xbonez The comma operator evaluates all the expressions and returns the value of the last one. Both codes are equivalent.
subclass Array - assuming your browser supports class, and subclassing Array
@JaromandaX ES6 has been published already, so browsers should implement it. But assuming that is part of being "mad enough" ;)
|
8

because arr.push returns the length of the array, you can't chain the shift like that

simply do this

function queue(arr, item) {
  arr.push(item);
  return arr.shift();
}

Comments

3

Absolutely and Immutably so

push

[1, 2].concat([3])
// [1,2,3]

shift

[1,2,3].filter((e, i, a) => i != 0)
// [2,3]

pop

[1,2,3].filter((e, i, a) => i != a.length - 1)
// [1,2]

unshift

[1,2,3].concat([0]).map((e, i, a) => i == 0 ? a[a.length - 1] : a[i-1])
// [0,1,2,3]

Using the 2nd param index and 3rd param array inside map and filter makes things pretty flexible. You can try more by using that approach.

Another (easier) way but slightly reckless and NOT immutable

push

Array.prototype.pushChain = function(item) {
  this.push(item)
  return this
}
[1,2,3].pushChain(4)
//[1,2,3,4]

Meaning you can use the prototype of an array and use the simpler methods you want to chain but simply return this and you are good but the downside is you could mess up other code relying on the Array to be as it is or possibly overriding some other method you didn't intend.

OR

Another approach is make a JavaScript ES6+ type class like so

class ImmutableChainedArray {
  constructor(arr) {
    this._arr = Array.isArray(arr) ? arr : []
  }
  push(item) {
    this._arr = this._arr.concat([item])
    return this
  }
  pop() {
    this._arr = this._arr
      .filter((e, i, a) => i != a.length - 1)
     return this
  }
  shift() {
    this._arr = this._arr
      .filter((e, i, a) => i != 0)
    return this
  }
  unshift(item) {
    this._arr = this._arr
      .concat([item])
      .map((e, i, a) => i == 0 ? a[a.length - 1] : a[i-1])
    return this
  }
  // the rest of them are easy...

  val() {
    return this._arr
  }
}

then use like

const ica = new ImmutableChainedArray([1])
ica.unshift(0).push(2).shift().pop().val()
// ends up with [1]

Comments

2

There is sort of a hack using concat instead of push

function queue(arr, item) {
  return arr.concat([item]).shift();
}

Should get you the result you want.

1 Comment

the concat is not a true answer because it is immutable and create another array, so the developer lost the queue.
1

Actually, all answers are right and I wanna just add another way in ES6:

const Queue = (array, item) => { array.push(item); return array.splice(0,1); }

Or

const Queue = (array, item) => { array.push(item); return array.shift(); }

You shouldn't use concat instead of push because in your case you should mutate your myArr array because it is a queue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.