Convert columns to rows in javascript - javascript

I have read this Swap rows with columns (transposition) of a matrix in javascript However, it did not work for me (because I still stupi).
There are numbers of arrays each as individual colum like that:
id [1, 2, 3]
caption [one, two, three]
title [One, Two, Three]
I want to convert columns to row:
arr= [1, one, One]
...
Some code
var res = [];
for(i in this.fields) {
for(j in this.fields[i].value) {
res[j][i] = this.fields[i].value[j];
}
}
it give me "TypeError: can't convert undefined to object "
In php this method works fine, but could somebody point me how to do it in js. Thanks in advance.
UPDATE for simplication
var arr = [];
arr[0] = [];
arr[6][0] = 5;
/*
Exception: can't convert undefined to object
#Scratchpad/1:4
*/
When we scan common string we iterate with indexes like 0-0, 0-1, 0-2 until end-of-row when starts again 1-0 and so on. But here I need 0-0, 1-0, 2-0 end of col and again 1-0, 1-1, 1-1 ...
UPDATE for "this". Just add a cople of lines:
console.log(this.fields[i].value[j]);
console.log('indexes: i='+i, 'j='+j);
and as could you see there are no undefined values
4
indexes: i=0 j=0
1
indexes: i=1 j=0
1
indexes: i=2 j=0
one
indexes: i=3 j=0
One
indexes: i=4 j=0

There are a few mistakes in your source code. We donĀ“t know how your this.fields value looks like, but for the sake of your code snippet let it look like that:
this.fields = [
{ value: [1, 2, 3] },
{ value: [4, 5, 6] },
{ value: [7, 8, 9] }
]
If your this.fields variable looks like that, you are not so far away from the solution. Your error message says TypeError: can't convert undefined to object, so I am guessing your variable does not look like described.
When we transform your data in a form that looks like my example, your are not so far away from the solution in your code snippet. The problem is res does not know, that its second dimension is supposed to consist of arrays, because you never defined that. We can fix that by adding if(i === 0) res[j] = [];.
So with the described structure and our little fix, it should work:
var res = [];
for(i in this.fields) {
for(j in this.fields[i].value) {
if(i === 0) res[j] = [];
res[j][i] = this.fields[i].value[j];
}
}

For sure one error is within the loop itself. On the first iteration res[j] exists, but inside the inner loop res[j][i] is not defined and will throw an error. You could fix it by checking if the element already exists:
var res = [];
for(i in this.fields) {
for(j in this.fields[i].value) {
if( !res[j] ) { res[j] = []; }
res[j][i] = this.fields[i].value[j];
}
}

Related

Parsing JSON file to array, only puts last read value everywhere

I have the following code that basically, reads a JSON file, then puts it in a multidimensional array.
let fs1 = require('fs');
let root1 = fs1.readFileSync('myFile.json');
let data1 = JSON.parse(root1);
for(index1 in data1){
for(index2 in data1[index1]){
console.log(index1)
console.log(index2)
console.log(data1[index1][index2])
myArray[index1][index2] = data1[index1][index2]
}
}
The problem is that myArray is being filled EVERYWHERE with the last value in the JSON file even the console.log shows the good values/indexes/etc...
I'm quite new is JS so any help is welcome :D
Thanks in advance!
Juan
EDIT:
Finally solved. The problem was in myArray declaration.
Before it was like:
let v = [];
for (i = 0; i < n ; i++){
v[i] = 0;
}
let myArray = [];
for (i = 0; i < n ; i++){
myArray[i]= v;
}
And apparently it's all by reference, so the last value I assigned to myArray while reading data1 updated all of them.
Changed to:
let myArray = {};
for (i = 0; i < n ; i++){
myArray[i]= new Array();
}
for (i = 0; i < n ; i++){
for (j = 0; j < n ; j++){
myArray[i][j]= new Array();
}
}
And this works fine (probably there is some better solution
to initialize the array than this single + double for loop)
Thanks again guys! :D
I'm assuming you're trying to create some sort of object, of which contains some array(s)?
If so, you could do something like this?
Edit
Having read through some of the comments and whatnot, your issue is that you keep overwriting the value of myArrray[index1][index2], rather you should do something like my solution, or you could do some check within the outer loop, to see if myArrray[index1], if not, then assign it to be an array or an object, then worry about the other keys, aka index2.
With the map approach, at least you don't have to worry about checking if myArrray[index1] is an array, because map will just return an array.
const myArray = {};
// Object containing arrays example.
const dummyData1 = {
'array1': [1, 2, 3, 4],
'array2': [1, 2, 3, 4]
// etc...
};
Object.keys(dummyData1).forEach(key => {
myArray[key] = dummyData1[key].map(data => data);
});
console.log(myArray);
// Object containing objects example.
const dummyData2 = {
'object1': {
id: 1,
name: 'foo'
},
'object2': {
id: 2,
name: 'bar'
}
// etc...
};
Object.keys(dummyData2).forEach(key => {
myArray[key] = { ...dummyData2[key]};
});
console.log(myArray);
// Another example for the lols.
const dummyData3 = {
'arrayx': [1, 2, 3],
'arrayz': [4, 5, 6]
// etc...
};
Object.keys(dummyData3).forEach(key => {
myArray[key] = [...dummyData3[key]];
});
console.log(myArray);
Edit 2
Considering you can't seem to grasp the first coded example, to be fair, like you've said, you're new to JavaScript, so here's something that you may be able to understand as it's a lot more familiar to your example.
const myArray = {};
const data1 = {
'array1': {
a: 1,
b: 2,
c: 3
},
'array2': {
d: 4,
e: 5,
f: 6
}
};
for (let index1 in data1) {
myArray[index1] = myArray[index1] || [];
for (let index2 in data1[index1]) myArray[index1].push(data1[index1][index2]);
}
console.log(myArray);
Edit 3
Having learned that you come from a C++ background, maybe reading through pages such as this may be of some help?
Again, you're new to JavaScript, I won't make any assumptions regarding your skills or abilities to write JavaScript. Myself, originally I learned Java as my first language, so learning JavaScript wayback when was a little confusing to myself, an example being how class wasn't a thing back then, you had to define a class with a function, which wasn't a big deal, but it's just one of those things.

JS array concatenation for results of recursive flattening

Good day!
Task would be to get a flat version of an array, that may include some amount of nested arrays as well as other elements. For input [1, [2], [3, [[4]]]] output [1, 2, 3, 4] expected.
FreeCodeCamp spoiler alert.
Naturally, recursive solution comes to mind, e.g.:
function steamrollArray(arr) {
var result = [];
for(var i = 0; i < arr.length; i++){
//part of interest
if (Array.isArray(arr[i])){
var nestedElements = steamrollArray(arr[i]);
for(var j = 0; j < nestedElements.length; j ++){
result.push(nestedElements[j]);
}
//</part of interest>.
} else {
console.log("pushing: " + arr[i]);
result.push(arr[i]);
}
}
return result;
}
And it does it's thing. Result of sample run would be:
pushing: 1
pushing: 2
pushing: 3
pushing: 4
[1, 2, 3, 4]
And the question is: what goes awry, when we use concat to add nestedElements (that supposedly store return result of recursive call). If we are to change first if{} block in for loop (marked as part of interest) with snippet below:
if (Array.isArray(arr[i])){
var nestedElements = steamrollArray(arr[i]);
result.concat(nestedElements);
} else {
we will observe the following result:
pushing: 1
pushing: 2
pushing: 3
pushing: 4
[1]
My understanding was to pass the result of each recursive call to the concat function, which will add the returned array to the result, but for some reason it's not the case.
Questions on this task was asked, like this one, but those concerned with the flattening algorithm part, which is not questioned here.
I still fail to see the answer what exactly causes the difference. It very well might be something I simply overlooked in a hassle or as a result of my limited experience. Sorry if that's the case.
Array#concat returns a new array with the result.
The concat() method returns a new array comprised of the array on which it is called joined with the array(s) and/or value(s) provided as arguments.
So you need to assign the result:
result = result.concat(nestedElements);
// ^^^^^^ assignment
I am puzzled by the accepted answer as it can only concat two arrays. What you want for a nested array is actually:
var flatArray = [].concat.apply([], yourNestedArray);
this is my function.
function _recursive_array_flat( ...args )
{
var _ret_array = [];
for( _arg of args )
{
if ( _arg instanceof Array )
{
if ( _arg.length > 0 ) // work with consistent elements only
_ret_array = _ret_array.concat( _recursive_array_flat( ..._arg ) );
}
else _ret_array.push( _arg );
}
return _ret_array;
}
var _ret = _recursive_array_flat( [0], 1,2,3, [ 4,5,6, [ 7,8,9 ] ] );
console.log( _ret );

javascript - potential infinite loop when comparing with arguments.length

I am trying to write a for-loop that goes trough all the inputs of a function, compares the elements of the inputs, and outputs unique elements (in this case they will always be numbers).
Since this is a freecodecamp exercise, I get some feedback, and get the following error: Error: potential infinite loop at line 4.
If I run the loop, without the infinite loop protection I get out of memory. Can someone point out what I'm doing wrong?
function unite(arr1, arr2, arr3) {
//for all arrays
var output = arr1;
for(var x = 0; x < arguments.length; x++) {
for(var y = 0; y < arguments[x].length; y++) {
for(var i = 0; i < output.length; i++) {
if(arguments[x][y] !== output[i]) {
output.push(arguments[x][y]);
}
}
}
}
return output;
}
unite([1, 3, 2], [5, 2, 1, 4], [2, 1]);
I see two issues with your code.
1: You are adding items to an array as you iterate through it
You set output = arr1', then start walkingarr1as part ofarguments. Then you are adding items intoarr1/output` within the loop. These additional items are traversed and more items added.
2: The unique test is flawed
The first issue may not have been so bad if you ensured the items in the output array were unique. Unfortunately there is also an issue in your test for uniqueness in the output array. The current item is added for each entry in the output array that it doesn't match. If your output were [1,2,3,4] and the item you were comparing was 2, it would get pushed onto the output 3 times because it does not match 1, 3 or 4.

Emptying array when it matches another array

So, I'm trying to match 2 different arrays. If the same cells match, I want to remove that cell from one array using the .slice method.
Edit: What I'm trying to do is remove a number from array1 if array2 contains a matching number. The way the code works now is that it only deletes 1 entry. I want all the entries deleted from the first array.
array1 = [1, 2, 4, 5, 7, 10];
array2 = [1,2,4,5,6,7,8];
var misc = function deleteValues(array, arayy) {
for(var i = 0; i < array.length; i++) {
if ( arayy[i] == array[i]) {
array.splice(i, 1);
}
}
return array;
};
I try to run this and under console log, the array1 is unchanged. It seems like the splice method isn't removing any cells. I searched SE, but couldn't find anything that could help me.
jsFiddle Demo
The problem is that you are modifying one of the arrays as you iterate, but you are still using the same index. The end result is that you end up comparing the wrong indexes to each other after the first removal. Use two indexes, have one offset back down when it removes an item, and have the other simply iterate.
var misc = function deleteValues(array, arayy) {
for(var i = 0, j = 0; i < array.length; i++, j++) {
if ( arayy[j] == array[i]) {
array.splice(i--, 1);
}
}
return array;
};
It seems you want to remove items from the first array if the values are also in the second. The reduceRight method seems suitable as it iterates from right to left over the array, hence removing items doesn't affect the index of subsequent elements in the array. The same result can be achieved with a decrementing loop.
Also, I think function declarations are better than assignment of expressions, but each to their own.
var array1 = [1, 2, 4, 5, 7, 10];
var array2 = [1,2,4,5,6,7,8];
function deleteValues(arr0, arr1) {
arr0.reduceRight(function(x, value, index) {
if (arr1.indexOf(value) != -1) {
arr0.splice(index, 1);
}
},'');
// Not necessary but handy for chaining
return arr0;
}
document.write(deleteValues(array1, array2));
Using an arrow function, the above can be reduced to:
function deleteValues(arr0, arr1) {
arr0.reduceRight((x, v, i) => arr1.indexOf(v) != -1? arr0.splice(i, 1):'');
return arr0;
}

Maintaining array order in Javascript

I am new to JavaScript and I am having trouble working with my array, I want my array ordered how I explicitly write it and not how JavaScript decides it wants it.
If we have a array
var array = {
0: 'zero',
4: 'four',
2: 'two'
};
When I choose to display this in the console, or iterate over it, Its reordered like this
array = {
0: 'zero',
2: 'two',
4: 'four'
};
I have tried 2 loops so far, The for loop, and also the for loop with the in statement.
Both work according how I assumed they would as they use a key and work there way up/down, making order I specify is absolutely useless.
How can I write/print/work with my array as its ordered, In other languages such as PHP its as simple as
$array = array(
0 => 'zero',
4 => 'four',
2 => 'two'
);
foreach($array as $key => $value)
echo $key ."\n";
This would output
0
4
2
Thanks in advance.
You're using an object {}, not an array []. Objects have no explicit order, where Arrays do. That's why you're having your problem. Change your {} to [] and you'll be fine. You could even use an array of objects.
var array = [
{0: 'zero'},
{4: 'four'},
{2: 'two'}
];
Looping over that like so
for(var i = 0; i < array.length; i++){
console.log(array[i]);
}
Gives us our normal order.
Object {0: "zero"}
Object {4: "four"}
Object {2: "two"}
Another Edit: The problem is you're trying to have an array that has properties and values just like an object, without using an object, {property: value} - that can't really be done with an array. To loop over an array like you want, it's as simple as
var arr = [1,2,3]
and
for(var i = 0; i < arr.length; i++){
console.log(i) //1,2,3
}
but the problem, like mentioned above, is you want more complex arrays which you simply can't do.
You need to understand what an Array and what an Object are, they are fundamentally different things and do not behave the same.
Array
Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array's size length grow or shrink at any time, JavaScript arrays are not guaranteed to be dense. In general, these are convenient characteristics; but if these features are not desirable for your particular use, you might consider using typed arrays.
Examples of an Array, note the magical length property, the values assigned to an Array are always found at their indexed locations; index is from 0 to 2^32 - 1
// dense arrays
var array1 = [1, 2, 3];
array1.length === 3;
array1[0] === 1;
var array2 = [];
array2[0] = 1;
array2[1] = 2;
array2[2] = 3;
array2.length === 3;
array1[1] === 2;
var array3 = [];
array3.push(1);
array3.push(2);
array3.push(3);
array3.length === 3;
array3[2] === 3;
// and a sparse array
var array4 = [];
array4[0] = 1;
array4[2] = 2;
array4[4] = 3;
array4.length === 5;
array4[1] === undefined;
Iterating an array for
var array = [1, 2, 3, 4, 5];
for (var index = 0; index < array.length; index += 1) { // counts from (index) 0 to 4
console.log(index, array[index]); // outputs 0 1 \n 1 2 \n 2 3 \n 3 4 \n 4 5
}
Object
An object is a collection of properties, and a property is an association between a name and a value. A property's value can be a function, in which case the property is known as a method. In addition to objects that are predefined in the browser, you can define your own objects.
Examples of an Object, there is no magical length property.
var object1 = {
'zero': 1,
'one': 2,
'two': 3
};
object1.zero === 1;
var object2 = {);
object2['zero'] = 1;
object2['one'] = 2;
object2['two'] = 3;
object2.one === 2;
var object3 = {);
object3.zero = 1;
object3.one = 2;
object3.two = 3;
object['two'] === 3;
Iterating (enumerating) an object for..in
var object = {
one: 0,
two: 1,
three: 2
};
for (var property in object) {
if (object.hasOwnProperty(property)) { // make sure the property belongs to object
console.log(property, object[property]); // outputs (not necessarily this order)
// three 2 \n two 1 \n one 0
}
};
If you are trying to maintain an ordered Object, then this is not how Javascript works and iteration (enumeration) of an object is arbitrary. There are techniques that you can use to iterate (enumerate) an Object in a known order. This requires that you keep an ordered list of properties in an array and use the array in the iteration process.
var object = {
'c': 1,
'z': 2,
'b': 3,
'a': 4
}
var propertyOrder = ['c', 'z', 'b', 'a'];
for (var index = 0; index < propertyOrder.length; index += 1) {
console.log(index, propertyOrder[index], object[propertyOrder[index]]); // outputs 0 c 1 \n 1 z 2 \n 2 b 3 \n 3 a 4
}
I don't get it. What makes you think that 0, then 4, then 2, is in any form or shape "in order"?
However, apparently what you want is to keep the number and the string together, in the order that you specify.
Your mistake, if you'll excuse me for perhaps sounding a bit harsh, is that you seem to think that you can use indices or member names to be both a means to access data and part of the data itself.
You can't, and you shouldn't. An index is an index, a name is a name, and data is data [1].
Here are two implementations of keeping your numbers and strings together:
var pairs = [
[0, "zero"],
[4, "four"],
[2, "two"]
];
for (var index in pairs) {
alert(pairs[index][0] + ": " + pairs[index][1]);
};
For this one, I keep the pairs of numbers and strings together in arrays of their own: the numbers at position 0, the strings at position 1. I store these arrays in pairs.
Then I iterate over array with for/in, which, in each iteration, gives me an index of my pairs array.
I then use that index to access the right sub-array in pairs, and get the number from position 0 and the string from position 1.
var pairs = [
{number: 0, string: "zero"},
{number: 4, string: "four"},
{number: 2, string: "two"}
];
for (var index in pairs) {
alert(pairs[index].number + ": " + pairs[index].string);
};
This one works exactly the same, except of storing the pairs in arrays, I store them in objects.
This has the added bonus of better readability inside the for loop: pairs[index][0] and pairs[index][1] do not really convey a clear meaning. It tells us nothing more than, "of the pair with the given index, get items 0 and 1".
However, pairs[index].number and pairs[index].name are much clearer: "of the pair with the given index, give me the number and the name."
_
Footnotes:
[1a] A number is a number: my bank account number is just that: a means to identify my bank account. It doesn't convey any meaning as to my name, my PIN, or the balance on my account -- all attributes that would qualify as data belonging to my bank account.
[1b] A name is a name: my name is just a name. When you're talking about me, you can use my name to refer to me, so that others know whom you are talking about. My name does not convey any information about my hobbies, my SSN, or what brand of car I have -- all attributes that would qualify as data that would describe certain aspects of me. (However, by convention, you can often tell a person's gender by their name)

Categories