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.
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--;
}
}
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.
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]
Related
this the forth project from the odin project, all tests passed but the fifth one which required removing all elements failed and when i run the code it returns an array with half elements in original array before mutating.
I don't know why IT DOESN'T RETURN AN EMPTY ARRAY.in the fifth test.
const removeFromArray = function (array, ...deleteElement) {
for (let i = 0; i < array.length; i++) {
if (array.includes(deleteElement[i])) {
array.splice(array.indexOf(deleteElement[i]), 1);
}
}
return array;
};
const randomArray = [1, 2, 3, 4];
console.log(removeFromArray(randomArray, 1, 2, 3, 4));
and this the test
const removeFromArray = require('./removeFromArray')
describe('removeFromArray', () => {
test('removes a single value', () => {
expect(removeFromArray([1, 2, 3, 4], 3)).toEqual([1, 2, 4]);
});
test('removes multiple values', () => {
expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]);
});
test('ignores non present values', () => {
expect(removeFromArray([1, 2, 3, 4], 7, "tacos")).toEqual([1, 2, 3, 4]);
});
test('ignores non present values, but still works', () => {
expect(removeFromArray([1, 2, 3, 4], 7, 2)).toEqual([1, 3, 4]);
});
test.skip('can remove all values', () => {
expect(removeFromArray([1, 2, 3, 4], 1, 2, 3, 4)).toEqual([]);
});
test.skip('works with strings', () => {
expect(removeFromArray(["hey", 2, 3, "ho"], "hey", 3)).toEqual([2, "ho"]);
});
test.skip('only removes same type', () => {
expect(removeFromArray([1, 2, 3], "1", 3)).toEqual([1, 2]);
});
});
In the for you are looping trough the wrong element. It should be deleteElement.length, not array.length
const removeFromArray = function(array, ...deleteElement) {
for (let i = 0; i < deleteElement.length; i++) {
if (array.includes(deleteElement[i])) {
array.splice(array.indexOf(deleteElement[i]), 1);
}
}
return array;
};
const randomArray = [1, 2, 3, 4];
console.log(removeFromArray(randomArray, 1, 2, 3, 4));
EDIT:
although this will not work correctly when there are 2 same element to delete in the array. Here is another implementation which is deleting all matched indexes and not only the first one.
const removeFromArray = function(array, ...deleteElement) {
for (let i = 0; i < deleteElement.length; i++) {
let foundIndex = array.indexOf(deleteElement[i]);
while (foundIndex !== -1) {
array.splice(foundIndex, 1);
foundIndex = array.indexOf(deleteElement[i]);
}
}
return array;
};
const randomArray = [1, 2, 3, 1, 4];
console.log(removeFromArray(randomArray, 1));
Your function iterates over the wrong variable (array.length)
const removeFromArray = function (array, ...deleteElement) {
for (let element of deleteElement) {
if (array.includes(element)) {
array.splice(array.indexOf(element), 1);
}
}
return array;
};
The problem is that the for loop is using the array.length property dynamically, which means it is going to be evaluated every time you pass the loop, so since you are removing the elements from the original array, this value is not constant and at some point the array length value and the i counter will get out of sync.
You just need to save the array length value in a variable so it stays the same after you remove the objects from the array.
var arrLen = array.length;
for (let i = 0; i < arrLen; i++) {
...
}
Update:
Pasting the full code here plus a live sample:
https://jsfiddle.net/bcngr/sbk1yhmn/
const removeFromArray = function (array, ...deleteElement) {
var arrLen = array.length; // Save the length value before any modification to the array
for (let i = 0; i < arrLen; i++) { // use the variable instead of array.length
if (array.includes(deleteElement[i])) {
array.splice(array.indexOf(deleteElement[i]), 1);
}
}
return array;
};
const randomArray = [1, 2, 3, 4];
console.log(removeFromArray(randomArray, 1, 2, 3, 4));
I have two solutions for the same problem (both work), one is mine and the other one is from the internet.
In the internet's solution they add the variable modifiedArray. What is the point of doing that?
In the internet's solution, is the [...arr] in the modifiedArray variable not the same that the argument arr on the function removeFromArray()?
My solution:
const removeFromArray = function(arr, ...Args) {
for (i = 0; i <= Args.length; ++i) {
if (arr.includes(Args[i])) {
arr.splice(arr.indexOf(Args[i]), 1)
}
}
return arr;
}
module.exports = removeFromArray
Internet's solution:
const removeFromArray = function(arr, ...Args) {
let modifiedArray = [...arr]
for (i = 0; i < arr.length; ++i) {
if (modifiedArray.includes(Args[i])) {
modifiedArray.splice(modifiedArray.indexOf(Args[i]), 1)
}
}
return modifiedArray;
}
module.exports = removeFromArray
Test for both answers:
const removeFromArray = require('./removeFromArray')
describe('removeFromArray', function() {
it('removes a single value', function() {
expect(removeFromArray([1, 2, 3, 4], 3)).toEqual([1, 2, 4]);
});
it('removes multiple values', function() {
expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]);
});
it('ignores non present values', function() {
expect(removeFromArray([1, 2, 3, 4], 7, "tacos")).toEqual([1, 2, 3, 4]);
});
it('ignores non present values, but still works', function() {
expect(removeFromArray([1, 2, 3, 4], 7, 2)).toEqual([1, 3, 4]);
});
it('can remove all values', function() {
expect(removeFromArray([1, 2, 3, 4], 1, 2, 3, 4, 5)).toEqual([]);
});
it('works with strings', function() {
expect(removeFromArray(["hey", 2, 3, "ho"], "hey", 3)).toEqual([2, "ho"]);
});
it('only removes same type', function() {
expect(removeFromArray([1, 2, 3], "1", 3)).toEqual([1, 2]);
});
});
The difference between your code and the other one, is that yours changes the arr parameter directly whereas the other first makes a copy of the array, and then modifies that copy.
When you pass an array to a function, you are actually passing a reference to that array, not a copy of it. This means that when you modify arr directly, you are also modifying the source array.
Here is a nice example:
const removeFromArray1 = function(arr, ...Args) {
for (i = 0; i <= Args.length; ++i) {
if (arr.includes(Args[i])) {
arr.splice(arr.indexOf(Args[i]), 1)
}
}
return arr;
}
const removeFromArray2 = function(arr, ...Args) {
let modifiedArray = [...arr]
for (i = 0; i < arr.length; ++i) {
if (modifiedArray.includes(Args[i])) {
modifiedArray.splice(modifiedArray.indexOf(Args[i]), 1)
}
}
return modifiedArray;
}
const arr1 = [1, 2, 3, 4];
console.log('Returned array 1', removeFromArray1(arr1, 3));
console.log('Source array 1', arr1);
const arr2 = [1, 2, 3, 4];
console.log('Returned array 2', removeFromArray2(arr2, 3));
console.log('Source array 2', arr2);
Here you can see that arr1 is modified after calling removeFromArray1, but arr2 is not modified after calling removeFromArray2. Changing the source array might have odd side-effects if you try to use the initial array expecting it not to be changed.
let modifiedArray = [...arr] is a simple way to make a shallow copy of the array.
The second solution is nearer to functional programming pattern (pure function).
In functional programming you dont push or delete items into existing arrays or objects.
You would rather create a new array with all the same items as the original array, Then you modify the duplicate and return it. The duplication is done by
let modifiedArray = [...arr]
The concept is described as pure Function. A function should not change anything outside the function. No side effects.
var arr = [1, 2, 3, 4, 5]
var length = 0 while (true) { if (arr.charAt(length) == '') { break } else { length++ } } console.log(length)
arr.length is the suggested method to find the length of an array.
If you still want to use while loop to find the length. Use below code
const arr = [1, 2, 3, 4, 5];
let i = 0;
while (arr[i]) {
i++;
}
console.log(i);
Im trying to retrieve the not included value in the second array, by using the following code:
function diffArray(arr1, arr2) {
var newArr = [];
for (let i of arr1) {
if (arr2.includes(i)) {
newArr.push(i)
}
}
return newArr
}
console.log(
diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5])
)
Is there any way I can use another method to do this. I tried indexOf but I don't want the index.
Thank you
You can use filter():
let arr1 = [1, 2, 3, 5];
let arr2 = [1, 2, 3, 4, 5];
let result = arr2.filter(a2 => !arr1.includes(a2));
console.log(result);
if (!arr2.includes(i)) {
newArr.push(i)
}
! means not
You could always use else as well, but it's more lines of code:
if (arr2.includes(i)) {
// newArr.push(i)
} else {
newArr.push(i);
}
const a1 = [1, 2, 3, 4, 5];
const a2 = [1, 2, 3, 5];
function diffArray(arr1, arr2) {
const frequencies = arr1.concat(arr2).reduce((frequencies, number) => {
const frequency = frequencies[number];
frequencies[number] = frequency ? frequency + 1 : 1;
return frequencies;
}, {});
return Object.keys(frequencies).filter(number => frequencies[number] === 1);
}
I have two arrays and want to remove duplicates using filter function.
Here is my code:
arr1 = [1, 2, 3, 1, 2, 3];
arr2 = [2, 3];
result = [1, 1];
var result = arr1.filter(function(value, index) {
for (var i = 0; i <= arr2.length; i++) {
if (value !== arr2[i]) {
return value === arr2[i];
}
}
}
Thanks in advance! Any help would be great!
You can try to convert arguments into array and then check if the value from the initial array is in arguments array:
function destroyer(arr) {
// Converting arguments into array
var args = Array.prototype.slice.call(arguments);
arr = arr.filter(function (val) {
return args.includes(val)===false;
});
return arr;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3); // returns[1,1]
First of all, if its not a problem adding a library. I am using uniq from underscore.js.
uniq_.uniq(array, [isSorted], [iteratee]) Alias: unique
Produces a duplicate-free version of the array, using === to test object
equality. In particular only the first occurence of each value is
kept. If you know in advance that the array is sorted, passing true
for isSorted will run a much faster algorithm. If you want to compute
unique items based on a transformation, pass an iteratee function.
_.uniq([1, 2, 1, 4, 1, 3]);
=> [1, 2, 4, 3]
Other solution is using pure JS:
var newArray = [1, 2, 2, 3, 3, 4, 5, 6];
var unique = newArray.filter(function(itm, i, a) {
return i == newArray.indexOf(itm);
});
alert(unique);
But first you will need to combine your arrays in a new array:
var newArray = arr1.concat(arr2);
JS Fiddle
I hope this helped! :)
Here's one way without the filter function:
var arr1 = [1, 2, 3, 1, 2, 3];
var newArr = [];
for(var i = 0;i < arr1.length;i++){
if (newArr.indexOf(arr1[i]) === -1) {
newArr.push(arr1[i]);
}
}
Just use Array.prototype.filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
with Array.prototype.indexOf()
The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.
var arr1 = [1, 2, 3, 1, 2, 3],
arr2 = [2, 3],
result = arr1.filter(function (a) {
return !~arr2.indexOf(a);
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
As in this JS Fiddle, using filter()
arr1 = [1, 2, 3, 1, 2, 3];
arr2 = [2, 3];
result = [1, 1];
var result = arr1.filter(myFunc);
function myFunc(value) {
for (var i = 0; i < arr2.length; ++i) {
// to remove every occurrence of the matched value
for (var j = arr1.length; j--;) {
if (arr1[j] === arr2[i]) {
// remove the element
arr1.splice(j, 1);
}
}
}
}
document.getElementById('result').innerHTML = arr1;
console.log(arr1);
// Output: [1,1]
<div id="result"></div>