4

i have one object that one of the properties is an array of objects, the idea is to move objects from that array to no new one if one condition is true.

public $onInit(): void {
  this.getTicket();
}

public ticket: any; // Object with the array
public comments: any = []; // New array to move the elements
public getTicket(): void {
    this.ticketService
        .getTicketComplete(this.$stateParams.ticketID)
        .then((response: any) => {
            this.ticket = response;
            this.stringToDate(this.ticket);
            this.ticket.messages.forEach((elem, index) => {
                if (elem.type === "comment") {
                    this.ticket.messages.splice(index, 1);
                    this.comments.push(elem);
                }
            });
            console.log(this.ticket);
    });
}

the problem that i have is the next one: the array has to types of objects, messages and comments, if the array has 2 messages and 3 comments it should push to the new array 3 comments and leave 2 messages, but is moving only 2 comments.

Any idea. Thanks for your help.

Vega
  • 27,856
  • 27
  • 95
  • 103
Miguel Frias
  • 2,544
  • 8
  • 32
  • 53
  • 3
    Maybe the cause is that you modify the `array` inside the `forEach`-loop? – Arg0n Aug 28 '17 at 13:11
  • 1
    You should use the `filter()` method to filter which type of elements you want to remove **after** you have inserted your elements in your `comments` object – Alex Beugnet Aug 28 '17 at 13:14
  • yeah the idea is loop the `array` searching for the elements and remove the element from the array and push it in to a new....is there any way to do that outside of the `forEach` loop....? – Miguel Frias Aug 28 '17 at 13:15

3 Answers3

14

This is the way You do it:

var array1 = [1, 2, 3, 4, 5];
var array2 = [];

array1.forEach(function(elem, index) {
  array1.splice(index, 1);
  array2.push(elem);
});

console.log(array1); //[2, 4]
console.log(array2); //[1, 3, 5]

This is an example of how it can be done:

var array1 = [1, 2, 3, 4, 5];
var array2 = [];

for(var i = 0; i < array1.length; i++) {
  array2.push(array1[i]);
  array1.splice(i, 1);
  i--; //decrement i IF we remove an item
}

console.log(array1); //[]
console.log(array2); //[1, 2, 3, 4, 5]

Specific use-case for you:

let messages = this.ticket.messages;
for(let i = 0; i < messages.length; i++) {
  let message = messages[i];
  if (message.type === "comment") {
    this.comments.push(message);
    messages.splice(i, 1);
    i--;
  }
}
Arg0n
  • 8,283
  • 2
  • 21
  • 38
  • even if a push the element first and then remove it still leave one comment, the rest of then are push in to the new array. – Miguel Frias Aug 28 '17 at 13:23
  • 1
    See updated answer for what to replace your `forEach`-loop with (a `for`-loop). You problem was not when you push the element, but rather that the array now contains 1 element less. And you can't decrement `index` in a `forEach`-loop in any way that I know. – Arg0n Aug 28 '17 at 13:26
  • Thanks for the answer that was the problem is good to know that i can not decrement the index using `forEach` , thanks for your help, and thanks to the rest of the people how give ideas too. – Miguel Frias Aug 28 '17 at 13:32
  • why the OP solution fails to work? it seems functional at first hand, could be appreciable to have some comments on here please – Webwoman Feb 24 '19 at 13:14
  • @Webwoman `index` does not get decremented in the first code snippet, so we only move half of the elements (since the array is changed while looping). – Arg0n Feb 25 '19 at 07:53
0

You are removing elements as you loop through your array - this is never a good idea. A better way to solve this issue is to add them to this.comments first and when the foreach is finalized, start looping over this.comments and remove those that are in this array out of the messages.

sander
  • 719
  • 2
  • 9
  • 21
0

Here we go the async way baby:

var array1 = [1, 2, 3, 4, 5];
var array2 = [];

async function fillArray() {
  array1.forEach(function(elem, index) {
    console.log("elem: ", elem)
    array2.push(elem); 
  })
}

async function emptyArray(){
  fillArray().then(() =>{
    array1.length = 0; 
 })
}

emptyArray().then(() => { 
  console.log("array1: ", array1); //[]
  console.log("array2: ", array2); //[1, 2, 3, 4, 5]
})

An another great move, conditional way, cheer:

var array1 = [1, 2, 3, 4, 5];
var array1Length= array1.length;
var array2 = [];
 
  array1.forEach((elem, index) => {
    array2.push(elem); 
    if(array2.length === array1Length) array1.length=0
  })
  
  console.log("array1: ", array1); //[]
  console.log("array2: ", array2); //[1, 2, 3, 4, 5] 
Webwoman
  • 10,196
  • 12
  • 43
  • 87