Modify an array of dictionaries, to add an element in each - javascript

How could I add an additional key value pair to each element in the following array.
get_project_list.completed = [{"user":"xyz","email":"a#123.com"}]
for (var i in get_project_list.completed) {
i['status'] = "completed";
}
O/P [{"user":"xyz","email":"a#123.com","status":"completed"}]
There should be a simple solution to this but couldn't find one which worked.
Any help is appreciated.

Don't use for in loop for arrays, because it iterates over every enumerable property.
For example here I add to the array a new property, which is enumerable and in the for in loop I get it also.
var arr = [{"user":"xyz","email":"a#123.com"}];
Object.defineProperty(arr, 'custom', { value: 'myCustom', enumerable: true });
for(let prop in arr){
console.log(prop);
}
If you are using ES6 you can do via
1) forEach function
var arr = [{"user":"xyz","email":"a#123.com"}];
arr.forEach(item => item['status'] = 'completed');
console.log(arr);
2) for of loop
var arr = [{"user":"xyz","email":"a#123.com"}];
for(let item of arr){
item['status'] = 'completed';
}
console.log(arr);
With ES5, you can use simple for loop
var arr = [{"user":"xyz","email":"a#123.com"}];
for(var i = 0; i < arr.length; i++){
arr[i]['status'] = 'completed'; // get the current index-th item
}
console.log(arr);

You get the index in the for loop and need to use it together with the array.
get_project_list.completed[i]['status'] = "completed";
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
var get_project_list = { completed: [{"user":"xyz","email":"a#123.com"}] },
i;
for (i in get_project_list.completed) {
get_project_list.completed[i]['status'] = "completed";
}
console.log(get_project_list);
For arrays, I suggest to use a for loop with a counter, because you get all enumerable properties and the order is not guaranteed.
var get_project_list = { completed: [{"user":"xyz","email":"a#123.com"}] },
i;
for (i = 0; i <get_project_list.completed.length; i++) {
get_project_list.completed[i]['status'] = "completed";
}
console.log(get_project_list);

If you're transpiling (e.g. with Babel), I'd suggest using a map function in combination with the object spread operator instead.
let newList = get_project_list.completed.map(i =>
{... i, status : "completed" }
)
This way, you don't have to mutate the old array.

Related

Compute the what was added or remove from new and original array

this seems pretty silly to ask but I'm moving a bit away from PHP to javascript and have a bit of a hard time with 2 arrays one the original values and the other the new values.
I need to take take action on any values removed (run some function) and on any new values that where added.
Here is what I came up with so far, but it doesn't seem right.
// new values
var array1 = [ 'aaaa', 'R26i9vjDHE', 'bbbbb' ];
// original values
var array2 = [ 'U8G5AQVsX6', 'R26i9vjDHE', '7IkuofIHEu','aaaa'];
for (var i = 0; i < array2.length; i++) {
if(array1.indexOf(array2[i]) != -1) {
console.log('in new already?');
console.log(array2[i])
// do something with new inserted value
} else {
console.log('removed items');
console.log(array2[i])
// do something with a removed value
}
}
I'm used to php's in_array in a loop or various other php tool box items.
Suggestions?
my fiddle https://jsfiddle.net/xv8ah2yf/8/
So an element that was removed will be in array2, but not array1, and then an element added will be in array1 but not array2. So to detect both cases you'll need to loop through both arrays. You can do something like
var i;
for (i = 0; i < array2.length; i++) {
if (array1.indexOf(array2[i]) === -1) {
//item removed from array2
console.log(array2[i] + ' removed');
}
}
for (i = 0; i < array1.length; i++) {
if (array2.indexOf(array1[i]) === -1) {
//item added to array1
console.log(array1[i] + ' added');
}
}
Then take the appropriate action when each case is detected.
Let's just define what is meant be "added" and "removed":
added: in new array but not in original.
removed: in original but not in new array.
We can use 2 for-loops to determine these two types of elements:
let original_array = ['abc', 'def', 'ghi'];
let new_array = ['def', 'jkl', 'mno'];
for (let i = 0; i < new_array.length; i++){
if (!original_array.includes(new_array[i])){
console.log(new_array[i], 'has been added');
//further actions...
}
}
for (let i = 0; i < original_array.length; i++){
if (!new_array.includes(original_array[i])){
console.log(original_array[i], 'has been removed');
//further actions...
}
}
This should do it:
function compute(original, modified, addedCB, removedCB) {
for (let i of modified) {
if (!original.includes(i)) {
// this is a new value
addedCB(i);
}
}
for (let i of original) {
if (!modified.includes(i)) {
// the modified array doesn't include this value
removedCB(i);
}
}
}
You can get close to PHP's in_array with javascript's array.includes. You can use that to then filter the arrays in question:
This is a little slower than doing everything in a for loop, but also more succinct and cleared (IMO):
// new values
var array1 = [ 'aaaa', 'R26i9vjDHE', 'bbbbb' ];
// original values
var array2 = [ 'U8G5AQVsX6', 'R26i9vjDHE', '7IkuofIHEu','aaaa'];
// in array1 but not in array2
let not_in_array2 = array1.filter(item => !array2.includes(item))
// in array2 but not in array1
let not_in_array1 = array2.filter(item => !array1.includes(item))
// in both arrays
let inBoth = array1.filter(item => array2.includes(item))
console.log("Not in array1:", not_in_array1)
console.log("Not in array2:", not_in_array2)
console.log("In both:", inBoth)
From there you can forEach() or map() over the results and apply whatever function you want.

Remove data from an array comparing it to an other array

I am trying to compare the items in "item" array and the copyofOpList array to retrieve the data occurrences in copyofOpList
this is my try:
var _deleteUsedElement1 = function(item) {
for (var i = 0; i < item.length-1; i++){
for (var j = 0; j< $scope.copyofOpList.length-1; j++){
if (item[i].operationCode == $scope.copyofOpList[j].code) {
$scope.copyofOpList.splice(j, 1);
} } } };
$scope.compareArrays = function() {
...Get data from web Service
_deleteUsedElement1(item);
}
the copyofOpList array has 14 elements,and the item array has 2 array
but my code deletes only one occurrence (the first),so please how can I correct my code,to retrieve any occurances in the copyofOpList array comparing to the item array
thanks for help
I'd try to avoid looping inside a loop - that's neither a very elegant nor a very efficient way to get the result you want.
Here's something more elegant and most likely more efficient:
var item = [1,2], copyofOpList = [1,2,3,4,5,6,7];
var _deleteUsedElement1 = function(item, copyofOpList) {
return copyofOpList.filter(function(listItem) {
return item.indexOf(listItem) === -1;
});
};
copyofOpList = _deleteUsedElement1(item, copyofOpList);
console.log(copyofOpList);
//prints [3,4,5,6,7]
}
And since I just noticed that you're comparing object properties, here's a version that filters on matching object properties:
var item = [{opCode:1},{opCode:2}],
copyofOpList = [{opCode:1},{opCode:2},{opCode:3},{opCode:4},{opCode:5},{opCode:6},{opCode:7}];
var _deleteUsedElement1 = function(item, copyofOpList) {
var iOpCodes = item.map(function (i) {return i.opCode;});
return copyofOpList.filter(function(listItem) {
return iOpCodes.indexOf(listItem.opCode) === -1;
});
};
copyofOpList = _deleteUsedElement1(item, copyofOpList);
console.log(copyofOpList);
//prints [{opCode:3},{opCode:4},{opCode:5},{opCode:6},{opCode:7}]
Another benefit of doing it in this manner is that you avoid modifying your arrays while you're still operating on them, a positive effect that both JonSG and Furhan S. mentioned in their answers.
Splicing will change your array. Use a temporary buffer array for new values like this:
var _deleteUsedElement1 = function(item) {
var _temp = [];
for (var i = 0; i < $scope.copyofOpList.length-1; i++){
for (var j = 0; j< item.length-1; j++){
if ($scope.copyofOpList[i].code != item[j].operationCode) {
_temp.push($scope.copyofOpList[j]);
}
}
}
$scope.copyofOpList = _temp;
};

Transform a string into an array of arrays in JavaScript

I'm searching the shortest method to transform a string like
"str1,str2,str3,..."
into an array of arrays like :
[["str1"], ["str2"], ["str3"]]
I could use a loop or an each, but I wonder if there is something more elegant.
You can make use of split() and map() like so:
// This could be turned into 1 line but is split here for readibility
var array = string.split(',');
array = array.map(function(value){
return [value];
});
Note: map() doesn't exist in all implementations, check out this article for more info on it.
If you are targeting an ES5 supporting browser you could use Array.map.
var array = "str1,str2,str3".split(",").map(function(token) {
return [token]
});
Tom Walter's answer is great, but in case you don't want to use map:
var str = "str1,str2,str3";
var arr = str.split(",");
var arrOfarrs = [];
for(var i = 0; i < arr.length; i++) {
arrOfarrs.push([arr[i]]);
}
Alternatively, you can add a map polyfill to add support for older browsers:
Array.prototype.map = Array.prototype.map || function(fn) {
var arr = [];
for(var i = 0; i < this.length; i++) {
arr.push(fn(this[i]));
}
return arr;
};
which would then allow you to do
var arr = str.split(",").map(function(val) {
return [val];
});

Objects within an Array

I have multiple objects like the one below, and I was wondering what the correct syntax would be for putting them all within a single array. I'm also wondering how to correctly cycle through all of the arrays.
var verbMap = [
{
infinitive: "gehen",
thirdPres: "geht",
thirdPast: "ging",
aux: "ist",
pastPart: "gegangen",
english: "go"
},
{
infinitive: "gelingen",
thirdPres: "gelingt",
thirdPast: "gelang",
aux: "ist",
pastPart: "gelungen",
english: "succeed"
}
];
I know the correct way to cycle through that above array is:
for(v in verbMap){
for(p in verbMap[v]){
}
}
If I wanted to cycle through a larger array holding multiple arrays like verbMap, what would be the correct way to do that?
Just put the verbMap arrays in another array.
var verbMaps = [verbMap1, verbMap2...]
The key thing to understand is that your verbMap is an array of object literals. Only use
for (k in verbMap)...
for object literals.
The correct way to loop thru an array is something like
for (var i = 0; i < verbMaps.length; i++) {
var currentVerbMap = verbMaps[i];
for (var j = 0; j < currentVerbMap.length; j++) {
var currentHash = currentVerbMap[j];
for (var k in currentHash) {
console.log(k, currentHash[k];
}
}
}
The following function outputs every value from a (possibly) infinite array given as a parameter.
function printInfiniteArray(value){
if (value instanceof Array){
for(i=0;i<value.length;i++){
printInfiniteArray(value[i]);
}
} else {
console.log(value);
}
}
Edited code. Thanks jtfairbank
Your array does not contain other arrays. It contains objects. You could try this to loop though it.
for(var i = 0; i < verbMap.length; i++)
{
var obj = verbMap[i];
alert("Object #"+ i " - infinitive: " + obj.infinitive);
}
You would treat the array like any other javascript object.
var arrayOfArrays = [];
var array1 = ["cows", "horses", "chicken"];
var array2 = ["moo", "neigh", "cock-adoodle-doo"];
arrayOfArrays[0] = array1;
arrayOfArrays[1] = array2;
You can also use javascript's literal notation to create a multi-dimentional array:
var arrayOfArrays = [ ["meat", "veggies"], ["mmmm!", "yuck!"] ];
To cycle through the array of arrays, you'll need to use nested for loops, like so:
for (var i = 0; i < arrayOfArrays.length; i++) {
var myArray = arrayOfArrays[i];
for (var j = 0; j < myArray.length; j++) {
var myData = myArray[0]; // = arrayOfArrays[0][0];
}
}
DO NOT USE For...in!!!
That is not what it was made for. In javascript, For...in can have some unwanted behaviors. See Why is using "for...in" with array iteration a bad idea? for more detail.
You can use jQuery.each to cycle through an array or object, without having to check which one it is. A simple recursive function to cycle through key-value pairs in a nested structure, without knowing the exact depth:
var walk = function(o) {
$.each(o, function(key, value) {
if (typeof value == 'object') {
walk(value);
} else {
console.log(key, value);
}
});
}

Delete zero values from Array with JavaScript

I have an array with name "ids" and some values like ['0','567','956','0','34']. Now I need to remove "0" values from this array.
ids.remove ("0"); is not working.
Here's a function that will remove elements of an array with a particular value that won't fail when two consecutive elements have the same value:
function removeElementsWithValue(arr, val) {
var i = arr.length;
while (i--) {
if (arr[i] === val) {
arr.splice(i, 1);
}
}
return arr;
}
var a = [1, 0, 0, 1];
removeElementsWithValue(a, 0);
console.log(a); // [1, 1]
In most browsers (except IE <= 8), you can use the filter() method of Array objects, although be aware that this does return you a new array:
a = a.filter(function(val) {
return val !== 0;
});
Use splice method in javascript. Try this function:
function removeElement(arrayName,arrayElement)
{
for(var i=0; i<arrayName.length;i++ )
{
if(arrayName[i]==arrayElement)
arrayName.splice(i,1);
}
}
Parameters are:
arrayName:- Name of the array.
arrayElement:- Element you want to remove from array
Here's one way to do it:
const array = ['0', '567', '956', '0', '34'];
const filtered = array.filter(Number);
console.log(filtered);
For non-trivial size arrays, it's still vastly quicker to build a new array than splice or filter.
var new_arr = [],
tmp;
for(var i=0, l=old_arr.length; i<l; i++)
{
tmp = old_arr[i];
if( tmp !== '0' )
{
new_arr.push( tmp );
}
}
If you do splice, iterate backwards!
For ES6 best practice standards:
let a = ['0','567','956','0','34'];
a = a.filter(val => val !== "0");
(note that your "id's" are strings inside array, so to check regardless of type you should write "!=")
Below code can solve your problem
for(var i=0; i<ids.length;i++ )
{
if(ids[i]=='0')
ids.splice(i,1);
}
ids.filter(function(x) {return Number(x);});
I believe, the shortest method is
var newList = ['0', '567', '956', '0', '34'].filter(cV => cV != "0")
You could always do,
listWithZeros = ['0', '567', '956', '0', '34']
newList = listWithZeros.filter(cv => cv != "0")
The newList contains your required list.
Explanation
Array.prototype.filter()
This method returns a new array created by filtering out items after testing a conditional function
It takes in one function with possibly 3 parameters.
Syntax:
Array.prototype.filter((currentValue, index, array) => { ... })
The parameters explain themselves.
Read more here.
The easy approach is using splice!!. But there's a problem, every time you remove an element your array size will constantly reduce. So the loop will skip 1 index the array size reduces.
This program will only remove every first zero.
// Wrong approach
let num = [1, 0, 0, 2, 0, 0, 3,];
for(let i=0; i<num.length; i++){
if(num[i]==0)
num.splice(i, 1);
}
console.log(num)
the output will be
[1,0,2,0,3]
So to remove all the zeros you should increase the index if you found the non-zero number.
let i = 0;
while(i<num.length){
if(num[i]==0){
num.splice(i,1);
}
else{
i++;
}
}
But there's a better way. Since changing the size of the array only affects the right side of the array. You can just traverse in reverse and splice.
for(let i=num.length-1; i>=0; i--){
if(num[i]===0)
num.splice(i,1);
}

Categories

Resources