Cannot access array before initilaisation during swap - javascript

Ive come to something strange
Im trying to swap the array value 0 with the array value 1
Ive found a previous post stating that this is possible
[arr[0], arr[1]] = [arr[1], arr[0]];
So I wanted to replicate that
let array_names = ["Dave", "johson", "Lime", "Key", "Freeman", "Chell", "Shepart", "Furious"]
[array_names[0], array_names[1]] = [array_names[1], array_names[0]]
However something strange happens
I get an error message stating that
ReferenceError: Cannot access 'array_names' before initialization
I have checked and there isnt a typo anywhere
Also yes I did initialize the array before doing any modificiation

Your code is totally correct, but due to a missing semicolon, the interpreter parsed your code differently..
let array_names = ["Dave", "johson", "Lime", "Key", "Freeman", "Chell", "Shepart", "Furious"]
[array_names[0], array_names[1]] = [array_names[1], array_names[0]]
The expression was evaluated as
["Dave", "johson", ...][array_names[0], array_names[1]]
The code is parsed as one line statement.
The right answer as stated by Shubhada is
let array_names = ["Dave", "johson", "Lime", "Key", "Freeman", "Chell", "Shepart", "Furious"]; //Terminate statement
[array_names[0], array_names[1]] = [array_names[1], array_names[0]];

JS is actually trying to interpret your code as :
// reduced for brevity
let array_names = ["Dave", "johson"][array_names[0], array_names[1]] = [array_names[1], array_names[0]]
It's trying to access the index [array_names[0], array_names[1]] of the array ["Dave", "johson"] and at that time, array_names not yet defined.
You can (should) use semicolon to fix that :
let array_names = ["Dave", "johson", "Lime", "Key", "Freeman", "Chell", "Shepart", "Furious"];
[array_names[0], array_names[1]] = [array_names[1], array_names[0]];
console.log(array_names);

I try following
let array_names = [
"Dave", "johson",
"Lime", "Key",
"Freeman", "Chell",
"Shepart", "Furious"
]
console.log(array_names)
array_names[0], array_names[1] = array_names[1], array_names[0]
console.log(array_names)
temp = array_names[0]
array_names[0] = array_names[1]
array_names[1] = temp
console.log(array_names)
and get the result
[
'Dave', 'johson',
'Lime', 'Key',
'Freeman', 'Chell',
'Shepart', 'Furious'
]
[
'Dave', 'johson',
'Lime', 'Key',
'Freeman', 'Chell',
'Shepart', 'Furious'
]
[
'johson', 'Dave',
'Lime', 'Key',
'Freeman', 'Chell',
'Shepart', 'Furious'
]
as in here. But with your code I obtain
[
'Dave', 'johson',
'Lime', 'Key',
'Freeman', 'Chell',
'Shepart', 'Furious'
]
[
'Dave', 'johson',
'Lime', 'Key',
'Freeman', 'Chell',
'Shepart', 'Furious'
]
where the elements are not swapped. I do not understand either.

Related

Grouping values into one array of objects from two objects based on differing keys

I need to group two objects into an array of objects.
Beginning objects:
{strIngredient1: 'Light rum',
strIngredient2: 'Lime',
strIngredient3: 'Sugar',
strIngredient4: 'Mint',
strIngredient5: 'Soda water'}
{strMeasure1: '2-3 oz ',
strMeasure2: 'Juice of 1 ',
strMeasure3: '2 tsp ',
strMeasure4: '2-4 '}
I would like the final array of object to look like this:
[
{ingredient: 'Light rum', measure: '2-3 oz'},
{ingredient: 'Lime', measure: 'Juice of 1'},
etc... (if no measure, fill with empty string)
]
I have tried parsing the objects into two arrays based on keys and values, then looping through both arrays and outputting the values based on the number in the keys, however there has to be a more efficient way of getting the desired outcome. Any suggestions?
You can loop over the keys of the ingredients object and create the desired array by slicing out the ingredient number and looking for the corresponding measure for that number.
const
ingredients = { strIngredient1: "Light rum", strIngredient2: "Lime", strIngredient3: "Sugar", strIngredient4: "Mint", strIngredient5: "Soda water" },
measurements = { strMeasure1: "2-3 oz", strMeasure2: "Juice of 1", strMeasure3: "2 tsp", strMeasure4: "2-4" },
result = Object.keys(ingredients).map((k) => ({
ingredient: ingredients[k],
measure: measurements[`strMeasure${k.slice(13)}`] ?? "",
}));
console.log(result);
You could separate the keys and build a new object.
const
data = [{ strIngredient1: 'Light rum', strIngredient2: 'Lime', strIngredient3: 'Sugar', strIngredient4: 'Mint', strIngredient5: 'Soda water' }, { strMeasure1: '2-3 oz ', strMeasure2: 'Juice of 1 ', strMeasure3: '2 tsp ', strMeasure4: '2-4 ' }],
keys = { strIngredient: 'ingredient', strMeasure: 'measure' },
result = data.reduce((r, o, i) => {
Object.entries(o).forEach(([key, value]) => {
const [, k, i] = key.match(/^(.*?)(\d+)$/);
(r[i - 1] ??= { ingredient: '', measure: '' })[keys[k]] = value;
});
return r;
}, []);
console.log(result);

How to spread this array object?

I have the following object:
const info = [{ name: 'John', address: 'america', gender: 'Male', job: 'SE' }];
And I need to spread this array object and get this as
form:{
name:"John",
address:"america",
gender:"Male",
job:"SE"
}
How can I do that?
You don't need spread for that unless you want to make a shallow copy of the object. Instead, just use the object that's in the array:
const form = info[0];
or as a property on an object:
const obj = {form: info[0]};
At that point, form/obj.form and info[0] are both pointing to the same object.
If you do want to make a shallow copy, then spread is useful:
const form = {...info[0]};
or
const obj = {form: {...info[0]}};
There, form/obj.form points to a new object that has a copy of info[0]'s properties.
You could destructure the array and take the wanted property as target.
const
info = [{ "name": "John", "address": "america", "gender": "Male", "job": "SE" }],
result = {};
[{ ...result.form }] = info;
console.log(result);

ES6 - Reorder an Array with respect to an Object

I have an array which is like :
const my_array = [
"S T"
"O P"
"Lend"
"GT"
"CT"
"AC"
];
and an object according to which this array is being reordered:
const AN_ORDER = {
'Lend': 1,
'C T': 2,
'S T': 3,
'AC': 4,
'O P': 5
};
for which there is already a solution done as
//keys and sortBy from Lodash
const new_array = keys(my_array);
return sortBy(new_array, ar => AN_ORDER[ar] || Number.MAX_SAFE_INTEGER);
this yields me new array as:
["Lend", "AC", "O P", "S T", "GT", "C T"]
I tried looking into documentation of this usage, but I do not understand the idea of second argument being used here in sortBy.
Now my need is to reorder the my_array in below sequence:
['Lend', 'C T', 'S T', 'GT', 'AC', 'O P']
Please help me understand the implementation and suggest a way I can reorder in the same logic.
Your key 'G T' is not in object 'AN_ORDER' so my output will look different than yours. but it's working right.
const myArray = [
'S T',
'O P',
'Lend',
'GT',
'C T',
'AC'
];
const AN_ORDER = {
'Lend': 1,
'C T': 2,
'S T': 3,
'AC': 4,
'O P': 5
};
const sortedCollection = _.sortBy(myArray, item => {
return AN_ORDER[item];
});
You have add array in second argument, here you can mention callback function or property name.
Here is the working solution
const my_array = [
"S T",
"O P",
"Lend",
"GT",
"C T",
"AC"
];
var AN_ORDER = {
"Lend": 1,
"C T": 2,
"S T": 3,
"AC": 4,
"O P": 5
};
console.log(_.sortBy(my_array, [a => {
return (AN_ORDER[a] || Number.MAX_SAFE_INTEGER);
}]));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>
Not sure what AN_ORDER represents, as there isn't enough information on what it represents exactly.
Uses the keys in AN_ORDER in the final array, because the specified output above uses that. Strips spaces before searching for matching keys, using a Set to search if they exist, and using an offset of 0.5 to insert non-existing keys into AN_ORDER for sorting.
const my_array = [
"S T",
"O P",
"Lend",
"GT",
"CT",
"AC"
];
const AN_ORDER = {
'Lend': 1,
'C T': 2,
'S T': 3,
'AC': 4,
'O P': 5
};
const keys = new Set(Object.keys(AN_ORDER).map(x=>x.replace(/\s/g,'')))
my_array.forEach( (x,i)=>!keys.has(x.replace(/\s/g,'')) && (AN_ORDER[x]=i+0.5) )
my_obj = _.sortBy(Object.entries(AN_ORDER), ([,x])=>x).map(([x,])=>x)
console.log(my_obj);
<script src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>

Finding row and column of a multidimensional array in javascript

I defined an array in javascript like this:
var chessboard = [];
chessboard.push(["a1", "b1", "c1","d1","e1","f1","g1","h1"]);
chessboard.push(["a2", "b2", "c2","d2","e2", "f2","g2","h2"]);
chessboard.push(["a3", "b3", "c3","d3","e3", "f3","g3","h3"]);
chessboard.push(["a4", "b4", "c4","d4","e4", "f4","g4","h4"]);
chessboard.push(["a5", "b5", "c5","d5","e5", "f5","g5","h5"]);
chessboard.push(["a6", "b6", "c6","d6","e6", "f6","g6","h6"]);
chessboard.push(["a7", "b7", "c7","d7","e7", "f7","g7","h7"]);
chessboard.push(["a8", "b8", "c8","d8","e8", "f8","g8","h8"]);
What I'm struggling to find out is how to find the index if the element is passed.
Example: If I pass "a5" the programme should be able to tell me (row,column) as (4,0)
**CODE:**
<!DOCTYPE html>
<html>
<head>
<title>Javascript Matrix</title>
</head>
<body>
<script>
var chessboard = [];
chessboard.push(["a1", "b1", "c1","d1","e1", "f1","g1","h1"]);
chessboard.push(["a2", "b2", "c2","d2","e2", "f2","g2","h2"]);
chessboard.push(["a3", "b3", "c3","d3","e3", "f3","g3","h3"]);
chessboard.push(["a4", "b4", "c4","d4","e4", "f4","g4","h4"]);
chessboard.push(["a5", "b5", "c5","d5","e5", "f5","g5","h5"]);
chessboard.push(["a6", "b6", "c6","d6","e6", "f6","g6","h6"]);
chessboard.push(["a7", "b7", "c7","d7","e7", "f7","g7","h7"]);
chessboard.push(["a8", "b8", "c8","d8","e8", "f8","g8","h8"]);
alert(chessboard[0][1]); // b1
alert(chessboard[1][0]); // a2
alert(chessboard[3][3]); // d4
alert(chessboard[7][7]); // h8
</script>
</body>
</html>
This is where I am right now.
EDIT2:
Thank you so much everyone :) I feel very happy.
It seems there are multiple ways to it!
What I'm trying to do is this >>
Find out the (row,column) of two squares.
Example:
Square 1: a4
Square 2: c7
||x,y|| = row1-row2, column1-column2
Now find out (x,y) from another 8x8 matrix/array.
And display data from matrix(x,y).
Since it's a chessboard you can get the info from the element itself, without iterating the board:
function findCoo(el) {
return [
el[1] - 1, // the row value - 1
el[0].codePointAt() - 'a'.codePointAt() // the column ascii value - ascii value of a
];
}
console.log("a5", findCoo("a5"));
console.log("d6", findCoo("d6"));
alert("a5" + ' ' + findCoo("a5"));
For frequent use, I suggest to take an object with the positions and return just an array with the coordinates of the wanted field.
var chessboard = [["a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1"], ["a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2"], ["a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3"], ["a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4"], ["a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5"], ["a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6"], ["a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7"], ["a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"]],
positions = Object.create(null); // empty object without prototypes
chessboard.forEach(function (a, i) {
a.forEach(function (b, j) {
positions[b] = [i, j];
});
});
console.log(positions['a5']); // [4, 0]
console.log(positions);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For getting a field name, you could use Number#toString, with a radix of 36 for letters.
function getField(i, j) {
return (j + 10).toString(36) + (i + 1).toString(10);
}
console.log(getField(4, 0)); // 'a5'
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can try something like this:
Logic:
Loop over all array chessBoard and iterate over every row.
Check if the value exists in the row.
If yes, return row as iterator and column as index
var chessboard = [];
chessboard.push(["a1", "b1", "c1","d1","e1","f1","g1","h1"]);
chessboard.push(["a2", "b2", "c2","d2","e2", "f2","g2","h2"]);
chessboard.push(["a3", "b3", "c3","d3","e3", "f3","g3","h3"]);
chessboard.push(["a4", "b4", "c4","d4","e4", "f4","g4","h4"]);
chessboard.push(["a5", "b5", "c5","d5","e5", "f5","g5","h5"]);
chessboard.push(["a6", "b6", "c6","d6","e6", "f6","g6","h6"]);
chessboard.push(["a7", "b7", "c7","d7","e7", "f7","g7","h7"]);
chessboard.push(["a8", "b8", "c8","d8","e8", "f8","g8","h8"]);
function findPosition(str){
for(var i = 0; i< chessboard.length; i++) {
var index = chessboard[i].indexOf(str);
if(index>=0) {
return "row: " + i + ", col: " + index;
}
}
}
console.log(findPosition('a5'));
console.log(findPosition('d5'));
Since what you're storing is a chessboard, so instead of traversing all the elements inside the array and do searching, you can add a method to chessboard and return the [row,column] by some simple calculation:
let chessboard = [["a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1"], ["a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2"], ["a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3"], ["a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4"], ["a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5"], ["a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6"], ["a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7"], ["a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8"]]
chessboard.findEl = (input) => ([input[1]-1 ,input[0].charCodeAt(0)-97])
console.log(chessboard.findEl("a5"))
console.log(chessboard.findEl("b4"))
Try this
function getElement(val){
var result;
for(var i=0;i<chessboard.length;i++){
result=chessboard[i].indexOf(val);
if(result!=-1){
result='[' + i+',' + result + ']';
break;
}
}
return result;
}
console.log(getElement("a5"));

Grouping JSON by values

Using the Lever job posting API, I'm getting JSON results sorted by location, and I'm trying to figure out how to group all those results by "team" within the results, like the Shopify careers page.
Here is the codepen and here is the JSON
I tried adding the following on line 38 of the codepen to try to grab the team values, but it's not outputting as expected (I'm getting one letter per line, which isn't helpful):
for (var x in _data[i].postings[j].categories.team)
I'm sure it's probably something super simple, but I'm definitely not a javascript guy. Any help would be much appreciated!
Assume , the JSON output is
outJSON =
[ {
team: "TeamA",
name: "Ahmed",
field3:"val3"
},
{
team: "TeamB",
name: "Ahmed",
field3:"val43"
},
{
team: "TeamA",
name: "Ahmed",
field3:"val55"
},
]
Then see the groupBy function in the DEMO below:
DEMO :
outJSON = [{
team: "TeamA",
name: "Ahmed",
field3: "val3"
}, {
team: "TeamB",
name: "Ahmed",
field3: "val43"
}, {
team: "TeamA",
name: "Ahmed",
field3: "val55"
}]
var groupBy = function(xs, key) {
return xs.reduce(function(rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
var groubedByTeam = groupBy(outJSON, 'team')
console.log(groubedByTeam);
Then , if you want to loop through categories (teams), get all categories in array :
Object.keys(groubedByTeam) // return ["TeamA","TeamB"]
then :
Object.keys(groubedByTeam).forEach(function(category) {
console.log(`Team ${category} has ${groubedByTeam[category].length} members : `);
groubedByTeam[category].forEach(function(memb,i){
console.log(`---->${i+1}. ${memb.name}.`)
})
});

Categories