I am having, what I believe to be, weird behaviour while trying to push onto an array. I see expected values when outputting the array. If I push onto the array and then output, I get repeated values. The code in question:
var test = "aab";
testA = test.split("");
permutations = [];
generatePermutations(testA, testA.length);
function generatePermutations(array, arrayLength) {
if (arrayLength === 1) {
console.log(array); // THIS OUTPUTS DIFFERENT PERMUTATIONS
permutations.push(array);
console.log(permutations); // VALUES IN ARRAY ARE ALL THE SAME
/*
permutations.push(array.join(""));
console.log(permutations);
SPLITTING THE STRING MAKES IT WORK FINE?!
*/
return;
}
for (var i = 0; i < arrayLength; i += 1) {
generatePermutations(array, arrayLength - 1);
if (arrayLength % 2 == 0) {
swapArrayElements(array, i, arrayLength - 1);
} else {
swapArrayElements(array, 0, arrayLength - 1);
}
}
}
function swapArrayElements(array, elementA, elementB) {
var temp = array[elementA];
array[elementA] = array[elementB];
array[elementB] = temp;
}
console.log(array) will output a permutation as expected. It will output all permutations as the function recurs:
[ 'a', 'a', 'b' ] [ 'a', 'a', 'b' ] [ 'b', 'a', 'a' ] [ 'a', 'b', 'a'
] [ 'a', 'b', 'a' ] [ 'b', 'a', 'a' ]
If I push the result onto another array, permutations.push(array), every element has the same value:
[ [ 'a', 'a', 'b' ], [ 'a', 'a', 'b' ], [ 'a', 'a', 'b' ], [
'a', 'a', 'b' ], [ 'a', 'a', 'b' ], [ 'a', 'a', 'b' ] ]
I get the expected result if I join the array whilst pushing it onto permutations: `permutations.push(array.join("")):
[ 'aab', 'aab', 'baa', 'aba', 'aba', 'baa' ]
what am I missing here? I cannot understand how array can contain a value that all of a sudden changes upon being pushed onto permutations.
For clarity, this is a freecodecamp task and I'm working towards finding non repeating permutations.
You are using the same array variable, which always references the same memory location. So whatever you change in that array, is changed independent of whether you access the array via array or via permutations, which has all its elements set to the same array reference.
You can solve this by adding copies of the arrays to the permutations array, like so:
permutations.push(array.slice(0));
Note that the array values you have consist of strings. If they were mutable objects which you also modified, then you would need to extend this solution further. But in your case the above is enough.
Related
I am trying to access java script object which is available in the below format:
[
{'To':'A','From':'X','Weight':5},
{'To':'A','From':'Y','Weight':7},
{'To':'A','From':'Z','Weight':6},
{'To':'B','From':'X','Weight':2},
{'To':'B','From':'Y','Weight':9},
{'To':'B','From':'Z','Weight':4}
]
How can I access above object to create array like below ?
[
[ 'A', 'X', 5 ],
[ 'A', 'Y', 7 ],
[ 'A', 'Z', 6 ],
[ 'B', 'X', 2 ],
[ 'B', 'Y', 9 ],
[ 'B', 'Z', 4 ]
]
You can
Use Array.map() and Object.values():
const arrOfArrs = arr.map( Object.values );
Use Lodash's _.map() and _.values() in the same manner:
const _ = require('lodash');
. . .
const arrOfArrs = _.map( arr , _.values );
You should, however, be aware that the order in which an object's properties are iterated over (and hence returned) is not guaranteed in any way by the Ecmascript/Javascript standard. It can vary from Javascript implementation to implementation, and can even change from execution to execution. The most common order in which things are returned is insertion order, but that's not guaranteed.
Use a map function:
const l = [
{'To':'A','From':'X','Weight':5},
{'To':'A','From':'Y','Weight':7},
{'To':'A','From':'Z','Weight':6},
{'To':'B','From':'X','Weight':2},
{'To':'B','From':'Y','Weight':9},
{'To':'B','From':'Z','Weight':4}
]
const newArray = l.map(el => [el.To, el.From, el.Weight])
console.log(newArray);
Well, you can use array method .map()
let arr = [
{'To':'A','From':'Y','Weight':7},
{'To':'A','From':'Z','Weight':6}
]
let result = arr.map(Object.values)
console.log(result)
let a = [{'To':'A','From':'X','Weight':5},{'To':'A','From':'Y','Weight':7},{'To':'A','From':'Z','Weight':6},{'To':'B','From':'X','Weight':2},{'To':'B','From':'Y','Weight':9},{'To':'B','From':'Z','Weight':4}]
let array = []
for(i in a){
let temp = [a[i]['To'], a[i]['From'], a[i]['Weight']]
array.push(temp)
}
console.log(array)
You could use this to ensure the correct order of items in inner array.
let arr = [{'To':'A','From':'X','Weight':5},{'To':'A','From':'Y','Weight':7},{'To':'A','From':'Z','Weight':6},{'To':'B','From':'X','Weight':2},{'To':'B','From':'Y','Weight':9},{'To':'B','From':'Z','Weight':4}]
let result = arr.map(obj => [obj.To, obj.From, obj.Weight]);
console.log(result);
I want to extract a subarray of Columns from a multidimensional array and mutate the original array to remove those columns in JavaScript
Ex: If I have an array
originalArray =
[
[A, B, C, D, E, F],
[a1,b1,c1,d1,e1,f1],
[a2,b2,c2,d2,e2,f2],
[a3,b3,c3,d3,e3,f3]
[
Where A,B,C,D,E,F are headers
and I want to extract columns [4,0,3] in this order I would get
subArray =
[
[E, A, D],
[e1,a1,d1],
[e2,a2,d2],
[e3,a3,d3]
[
originalArray =
[
[B, C, F],
[b1,c1,f1],
[b2,c2,f2],
[b3,c3,f3]
[
I found this:
Extract subarray from a multidimensional array and mutate the original array
which does this for rows
let subArray = originalArray.reduce((accumulator, current, index) => {
if (idxList.includes(index)) {
//if the current index is included in the idxList array,
//push the current value to the accumulator
accumulator.push(current);
} else {
//push the current value to the `tempArray`.
tempArray.push(current)
}
return accumulator;
}, []);
Then I will concatenate these two arrays
reorderedArray = [...subArray, ...originalArray]
Reduce seems like an interesting approach and it seems like it should be a simple fix but I have to admit I am having a hard time understanding Reduce
Thanks in advance for your assistance
You could add the missing indices to order and map the array by mapping nested array with the indices of order.
let
data = [['A', 'B', 'C', 'D', 'E', 'F'], ['a1', 'b1', 'c1', 'd1', 'e1', 'f1'], ['a2', 'b2', 'c2', 'd2', 'e2', 'f2'], ['a3', 'b3', 'c3', 'd3', 'e3', 'f3']],
order = [4, 0, 3],
seen = new Set(order),
i = 0;
while (order.length < data[0].length) {
while (seen.has(i)) ++i;
order.push(i++);
}
data = data.map(a => order.map(i => a[i]));
data.forEach(a => console.log(...a));
regular mapping seems like it would work:
function myFunction() {
var originalArray = SpreadsheetApp.getActive().getRange('Sheet1!A:F').getValues();
var subarray = originalArray.map(e=>[e[4],e[0],e[3]]);
originalArray = originalArray.map(e=>[e[1],e[2],e[5]]);
}
I've been using lodash for a while now and I really love the _.set and _.get methods.
I'm trying to solve a problem to get the deep key paths whose final value is a string, but when I'm too dumb for it. Spend 3 hours on it and can't find a perfect solution:
const myObject = {
a: 'myObject.a',
b: {
ba: 'myObject.b.ba',
bb: ['myObject.b.bb[0]'],
},
c: [
{ ca: 'myObject.c[0].ca' },
],
};
So I have myObject (that's far more nested in real life) and I want to get paths to the values, but only the final one.
The method would look like getDeepPaths(myObject) and would return in this case: ['myObject.a', 'myObject.b.ba', 'myObject.b.bb[0]', 'myObject.c[0].ca' ]
Did anyone solve something like this before?
Recursion is actually not that hard. Here's how you could solve this problem:
const myObject = {
a: 'myObject.a',
b: {
ba: 'myObject.b.ba',
bb: ['myObject.b.bb[0]'],
},
c: [
{ ca: 'myObject.c[0].ca' },
],
};
var stringLeaves = function(path, obj) {
if (typeof obj === 'string') {
return [path]
}
return Object.keys(obj)
.filter(k => obj.hasOwnProperty(k))
.map(k => stringLeaves(path + '.' + k, obj[k]))
.reduce((a,x) => a.concat(x), []); // this line flattens the array
};
console.log(stringLeaves('myObject', myObject));
The work is done by the stringLeaves function. In this function:
if the obj passed in as a parameter is a string, then just return the current path.
otherwise we assume that the object is an array, or a generic object, in which case we iterate through its properties:
for each property, call stringLeaves recursively, by passing in the adjusted path (current path + the new property name) and the object/value that resides at that particular key.
The convention of the function is that it returns an array of all possible matches. This is why:
for scalar string values I return an array (to keep things consistent)
I have the .reduce((a,x) => a.concat(x), []); line: to transform an array of arrays into one array that consists of all the values present in the original arrays.
Note that the function cannot deduce that your object is called myObject, so I passed that name as an initial path.
I'll provide a more generic solution that doesn't use lodash or other external dependencies
const traverse = function* (node, path = [])
{
if (Object (node) === node)
for (const [ key, value ] of Object.entries (node))
yield* traverse (value, [ ...path, key ])
else
yield [ path, node ]
}
We can easily step thru our data using a for loop. Notice the generator yields a path-value pair for each value in the original object. All primitive values are included in the output, not just strings this time
// add a non-string value for demo
const myObject = {
...
d: 1
};
for (const [ path, value ] of traverse (myObject)) {
console.log ('path', path)
console.log ('value', value)
console.log ('---')
}
// path [ 'a' ]
// value myObject.a
// ---
// path [ 'b', 'ba' ]
// value myObject.b.ba
// ---
// path [ 'b', 'bb', '0' ]
// value myObject.b.bb[0]
// ---
// path [ 'c', '0', 'ca' ]
// value myObject.c[0].ca
// ---
// path [ 'd' ]
// value 1
// ---
If we wanted to, we can collect all of the pairs using Array.from
Array.from (traverse (myObject))
// [ [ [ 'a' ], 'myObject.a' ]
// , [ [ 'b', 'ba' ], 'myObject.b.ba' ]
// , [ [ 'b', 'bb', '0' ], 'myObject.b.bb[0]' ]
// , [ [ 'c', '0', 'ca' ], 'myObject.c[0].ca' ]
// , [ [ 'd' ], 1 ]
// ]
As you may have noticed, I keep path as an array rather than making it a .-separated string. There's no need to make it into a string just to split it apart again later.
const lookup = (obj, [ key, ...path ]) =>
obj && key
? lookup (obj [key], path)
: obj
for (const [ path, value ] of traverse (myObject)) {
console.log ('path', path)
console.log ('value', value)
console.log ('lookup', lookup (myObject, path))
console.log ('---')
}
// path [ 'a' ]
// value myObject.a
// lookup myObject.a
// ---
// path [ 'b', 'ba' ]
// value myObject.b.ba
// lookup myObject.b.ba
// ---
// path [ 'b', 'bb', '0' ]
// value myObject.b.bb[0]
// lookup myObject.b.bb[0]
// ---
// path [ 'c', '0', 'ca' ]
// value myObject.c[0].ca
// lookup myObject.c[0].ca
// ---
// path [ 'd' ]
// value 1
// lookup 1
// ---
I am trying to pass a function that removes duplicates from an array. It should handle strings, object, integers as well. In my code so far I am showing that it will handle strings but nothing else. How can Imake this function universalto handle numbers,handle arrays,handle objects, and mixed types?
let unique = (a) => a.filter((el, i ,self) => self.indexOf(el) ===i);
In this function I hav unique() filtering to make a new array which checks the element and index in the array to check if duplicate. Any help would be appreciated.
i think the first you should do is to sort the array ( input to the function ). Sorting it makes all the array element to be ordered properly. for example if you have in an array [ 1, 3, 4, 'a', 'c', 'a'], sorting this will result to [ 1 , 3 , 4, 'a', 'a' , 'c' ], the next thing is to filter the returned array.
const unique = a => {
if ( ! Array.isArray(a) )
throw new Error(`${a} is not an array`);
let val = a.sort().filter( (value, idx, array) =>
array[++idx] != value
)
return val;
}
let array = [ 1 , 5, 3, 2, "d", "q", "b" , "d" ];
unique(array); // [1, 2, 3, 5, "b", "d", "q"]
let obj = { foo: "bar" };
let arraySize = array.length;
array[arraySize] = obj;
array[arraySize++] = "foo";
array[arraySize++] = "baz";
array[arraySize++] = obj;
unique(array); // [1, 2, 3, 5, {…}, "b", "baz", "d", "foo", "hi", "q"]
it also works for all types, but if you pass in an array literal with arrays or objects as one of its element this code will fail
unique( [ "a", 1 , 3 , "a", 3 , 3, { foo: "baz" }, { foo: "baz" } ] ); // it will not remove the duplicate of { foo: "baz" } , because they both have a different memory address
and you should also note that this code does not return the array in the same order it was passed in , this is as a result of the sort array method
Try using sets without generics. You can write a function as
Set returnUnique(Object array[]) {
Set set=new HashSet();
for (Object obj:array) {
set.add(obj);
}
return set;
}
I am very new to javascript.
I have written the simple code:
var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);
As expected, it prints:
[ { a: [ 'a' ] } ]
But then, when I append the following line to the previous code:
temp['b'] = ['b']
arr.push(temp);
console.log(arr);
I would have expected it to print:
[ { a: [ 'a' ] }, { a: [ 'a' ], b: [ 'b' ] } ]
But it prints:
[ { a: [ 'a' ], b: [ 'b' ] }, { a: [ 'a' ], b: [ 'b' ] } ]
Entire code for unexpected result:
var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);
temp['b'] = ['b']
arr.push(temp);
console.log(arr);
Why did the first element of array got updated?
The following code gave me expected result:
var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);
temp = {};
temp['a'] = ['a']
temp['b'] = ['b']
arr.push(temp);
console.log(arr);
How does adding temp = {} helped here?
Objects in Javascript are passed by reference. That is, only one object is created and the symbol that represents that object can be used but it will refer to the same object always.
Lets take a deeper look:
If I'm understanding your example correct, this part
var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
console.log(arr);
Creates a local variable temp to which you add ['a'] to. You then push that into arr.
So at this point, arr references the object temp and looks like this:
[ { a: [ 'a' ] } ]
When you do this:
temp['b'] = ['b']
arr.push(temp);
console.log(arr);
The temp symbol which points to the original object containing ['a'] is updated, and so the arr will also get updated, so arr contains this at that point:
[ { a: [ 'a' ], b: [ 'b' ] }, { a: [ 'a' ], b: [ 'b' ] } ]
Finally,
You then do this instead:
temp = {};
temp['a'] = ['a']
temp['b'] = ['b']
arr.push(temp);
console.log(arr);
This creates a separate global variable temp, onto which you add both
['a'] and ['b']. This is global because it does not have the var keyword in the declaration/initialization. This then gets pushed into the arr. However, since it's a global variable and not the original local variable, you see this instead:
[ { a: [ 'a' ] }, { a: [ 'a' ], b: [ 'b' ] } ]
In first case, arr[0] has temp's reference, arr[1] also has temp's reference. So, arr[0] and arr[1] have the same reference.
Hence updating the reference will update it everywhere where the reference is
being referred.
In second case however, when you do temp = {} you're just reassigning temp to a new reference, before pushing it. So, there's no relationship between the arr[0]'s reference, and hence updating temp now, only affects it.
The examples are not the same, it doesn't have to do with temp = {}.
In the first example you push temp twice, meaning arr has to references 2 temp.
After the first push you add another item to temp so within arr, if you had print it, you would have seen:
[ { a: [ 'a' ], b: [ 'b' ] } ]
So try this out on the console:
var temp = {}
var arr = []
temp['a'] = ['a']
arr.push(temp)
temp['b'] = ['b']
console.log(arr);
You'll see the result:
[ { a: [ 'a' ], b: [ 'b' ] } ]
Pushing another temp into arr is just going to result into two references into temp.
There are two data types in JavaScript - value types and reference types.
Value types are actually copied as they are sent between objects. This is because this is what you would expect for certain things like numbers and booleans.
Say I pass the number 1 to a function that stores it in an object A.
It would be surprising if I could then subsequently modify the value contained in A simply by modifying the value of the original number. Hence, pass by value. There are also optimizations that can be performed for value types.
Objects (i.e. everything other than number literals, boolean literals, null, undefined, and string literals*) are reference types in JavaScript and only their reference is passed around. This is largely for efficiency reasons. In your example, temp is an object. It is therefore passed by reference.
And so
temp['b'] = ['b']
Modifies the single existing instance of temp, thereby modifying the contents of arr, before you then also push temp into arr for a second time.
So you end up with an array containing two references to a single object temp, giving you the observed result.
* There is some complexity surrounding the string implementation that I am purposefully ignoring here.