Confused with object properties. How do I not get 'undefined'? - javascript

I’m trying to create an array consisting of an object for each letter in the alphabet with two properties. Letter and dd_array. Right now I’m setting dd_array = [], but I would like it to be the corresponding morseDic property.
So for instance _charObjArray[0] = {letter: 'a', dd_array: [0,1]}
Can I get some tips on how to code this best possible??
alpha_array = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
morseDic = {
a: [0,1],
b: [1,0,0,0],
c: [1,0,1,0],
d: [1,0,0],
e: [0],
f: [0,0,1,0],
g: [1,1,0],
h: [0,0,0,0],
i: [0,0],
j: [0,1,1,1],
k: [1,0,1],
l: [0,1,0,0],
m: [1,1],
n: [1,0],
o: [1,1,1],
p: [0,1,1,0],
q: [1,1,0,1],
r: [0,1,0],
s: [0,0,0],
t: [1],
u: [0,0,1],
v: [0,0,0,1],
w: [0,1,1],
x: [1,0,0,1],
y: [1,0,1,1],
z: [1,1,0,0]
}
function _alpha(_char, dd_array) {
this.letter = _char;
this.dd_array = dd_array;
}
var _charObjArray = []
for (i = 0; i < alpha_array.length; i++) {
var _charNow = alpha_array[i];
var __charNow = _charNow;
var __charNow = new _alpha(_charNow, "[]") // "[]" should be replaced with the _charNow corresponding property from morseDic
_charObjArray.push(__charNow)
}
console.log(_charObjArray);

In _alpha, instead of:
this.dd_array = dd_array;
...you use _char to index into the morseDic object:
this.dd_array = morseDic[_char];
...and then don't pass a second argument to _alpha at all.
But if you want to pass it to _alpha as an argument:
var __charNow = new _alpha(_charNow, morseDic[_charNow]);
In JavaScript, you can access object properties either with dot notation and a property name literal (obj.foo, or morseDic.a), or using brackets notation and a property name string* (obj["foo"] or morseDic["a"]). In the latter case, the string can be the result of any expression, including a variable lookup.
* In ES6, it'll be strings or Symbols.

Related

Going through an array of words and returning new array of numbers

I have a huge list of words that I parsed from words.txt file and filtered out numbers, punctuation characters and all word that have uppercase letters. Then I need to go through that array, taking every word and returning the values from letterScores object. As an output I always get NaN and since I am new at JS I have no clue how to make it work.
I also tried to use map() method instead of pushing values into an empty array, but got the same Not a Number output. I believe there should be easier way to achieve the same result that I am not aware of.
var text = fs.readFileSync("./words.txt").toString('utf-8');
var textByLine = text.split("\n")
//--------------------------------------------------------//
const task1 = () =>{
letterScores = {
a:1, e:1, i:1, o:1, u:1, l:1, n:1, s:1, t:1, r:1,
d:2, g:2,
b:3, c:3, m:3, p:3,
f:4, h:4, v:4, w:4, y:4,
k:5,
j:8, x:8,
q:10, z:10
}
let wordScores = []
let filtered = textByLine.filter((word) => !/\W|\d|[A-Z]/.test(word))
filtered.forEach((word) =>{
const newWord = [...word]
sum = 0
for (let letters in newWord){
sum += letterScores[letters]
}
wordScores.push(sum)
})
return wordScores
}
console.log(task1())
I was not sure if you had to split it by line. I left it in if you have to, but it creates a third nested array as you split it by line, then split it by word, but then the word needs to be split into characters for comparison. I have it set for a double nested loop, but left the third loop in if it is absolutely necessary.
Hope it helps
//var text = fs.readFileSync("./words.txt").toString('utf-8');
var text = 'The man ran quickly.\nI do not know why, but he did.';
//var textByLine = text.split("\n");
const task1 = () => {
letterScores = {
a: 1, e: 1, i: 1, o: 1, u: 1, l: 1, n: 1, s: 1, t: 1, r: 1,
d: 2, g: 2,
b: 3, c: 3, m: 3, p: 3,
f: 4, h: 4, v: 4, w: 4, y: 4,
k: 5,
j: 8, x: 8,
q: 10, z: 10
};
let wordScores = [];
//textByLine.forEach(function (words) {
let filtered = text.replace(/[^a-zA-Z0-9 !?]+/g, "");
words = filtered.toLowerCase();
var newLine = words.split(" ");
newLine.forEach(function (word) {
const newWord = word.split("");
sum = 0;
for (var i = 0; i < newWord.length; i++) {
sum += letterScores[newWord[i]];
}
wordScores.push(sum);
});
//});
return wordScores;
};
console.log(task1());

ES6 Destructing for objects

I am new to ES6 destructing. I have an object which contains another object. I want to store certain values from the nested object.
For example -
z = {g: 1, h: 2, i: {d1:5, d2:6, d3:7}}
When I do
let { g, i : {d1, d3}, ...less } = z
the less variable only stores h and not d2.
Is there a way to make it so it is
less = {h, i : {d2}}
No there is not. What you could do is
let { g, i: { d1, d3, ...less2 }, ...less } = z
let less = { ...less, i: less2 };
This extracts the remainder and merges them back together while preserving the shape.
No, unfortunately this is not possible.
You can however extract the missing values from i with a second rest spread:
let z = {g: 1, h: 2, i: {d1:5, d2:6, d3:7}};
let { g, i : {d1, d3, ...i_less}, ...rest_less } = z;
let less = { i: i_less, ...rest_less };
console.log(less)
This is my way, hope it could help.
let z = {
g: 1,
h: 2,
i: {
d1:5,
d2:6,
d3:7
}
}
let {g, i: {d1, d3, ...less1}, ...less2} = z
let less = {
i: less1,
...less2,
}
console.log(less); // output: {h: 2, i:{d2:6}}

Javascript: how to easily replace object value with data from 2nd object?

I currently have a situation where I have 2 objects that look like this:
object a = {n: 15, b: 12, v: 10, h: 9} and so on.
object b = {1: e, 2: b, 3: z, 4: w} and so on.
I need to take the values from object b and use them to replace the values in object a. the result would look like:
object c = {n: e, b: b, v: z} etc.
One important thing is that if there are more items in object b than in object a, I still need them added on to the end of object c. so if there are 3 more items in object b, perhaps something like this {24: a, 25: y, 26:w} would happen at the end.
My first thought, of course, is a loop where I would iterate over each item in object a and replace the 'value' with that from object b. But I didn't know if there was a better way, especially with my concern about making sure that all of the items from object b are included in the new object.
Because of that concern, an alternative could be to replace the keys in object b with the keys in object a instead. that way if object a runs out, the last items in object b would't be excluded.
I've also tried:
Object.assign(a, b);
but that only works if the keys are the same, so that won't work. I need whatever happens to match index to index for the two objects.
If it matters, I can change object b to be anything I want as it's static. So, I could do:
object b = [e, b, z] etc. or
object b = {e: e, b: b, z: z}
Whatever makes it easiest to do.
I appreciate any thoughts anyone might have or if you can point me in the direction of a good post covering something like this. I'm currently scouring the internet and trying anything that sounds like it might work but so far, nothing has fit.
It's also worth noting that at this point I'm using pure vanilla JS so if there is a library or something that would make this super easy, I'm open to that.
You could do something like the following
var objectA = {
b: "test",
a: "test2",
c: "test3",
d: "test4"
};
var objectB = ["new", "new2", "new3", "new4", "new5", "new6"];
var index = 0;
for (var prop in objectA) {
if (objectA.hasOwnProperty(prop)) {
objectA[prop] = objectB[index];
index++;
}
}
for(index; index < objectB.length; index++) {
objectA[index] = objectB[index];
}
Couple things though:
The for..in loop is based on order of implementation. So whatever order the properties were added to the object will be the order of the loop.
Functionality like what you are requesting seems like a code smell when viewed out of context. Typically you are not merging two objects like the way you are requesting. If you want to provide further context, a better solution might be offered up.
I am assuming that those letter values in object b are strings, but the example would also work on variables, you just have to remove the quotation marks.
My approach is:
1. Get all the keys in b and a
2. Create an empty object, Loop through the keys in b
3. Using the index of b, i can also get the index of a. This way, when we are iterating the 3rd time, i would be 2 and I can get the keys and values of a and b, which are v:10 and 3: 'z' respectively. Then I map the key of a to the value of b, so the result would be v: 'z'.
4. If b has more keys, just assign current key and value in b to c.
var a = {n: 15, b: 12, v: 10, h: 9};
var b = {1: 'e', 2: 'b', 3: 'z', 4: 'w', 24: 'a', 25: 'y', 26:'w'};
// get all the keys in a
let aKeys = Object.keys(a);
// get all the keys in b
let bKeys = Object.keys(b);
// acc is the accumulated object c,
// at the beginning value of c is {}, it gets bigger as we loop through the keys of b
// i is the ith key in b
let c = bKeys.reduce((acc, _, i) => {
// if a > b then put key value pair of b
if (i > aKeys.length - 1) {
acc[bKeys[i]] = b[bKeys[i]];
} else {
acc[aKeys[i]] = b[bKeys[i]];
}
return acc;
}, {});
console.log(c)
After doing a bit more searching and playing, something I read inspired me to make both objects into arrays instead and then join them into a map. Ended up being super easy. This was the result:
var a = ['a', 'b', 'c'];
var b = [1, 2, 3];
var map = {};
for(var i = 0; i < a.length; i += 1) {
map[ a[i] ] = b[i];
}
console.log(map); // {a: 1, b: 2, c: 3}
Thanks for those who read it!
var objectA = {n: 15, b: 12, v: 10, h: 9};
var objectB = {n: e, b: b, v: z, h: w, a: 1, c: 2};
var objectC = extend({}, objectA, objectB);
function extend(out){
out = out || {};
for (var i = 1, len = arguments.length; i < len; i++){
var obj = arguments[i];
if (!obj) continue;
for (var key in obj){
if (obj.hasOwnProperty(key))
out[key] = (typeof obj[key] === 'object') ? extend(out[key], obj[key])
: obj[key];
}
}
return out;
}
console.log(objectC);
// outputs {n: e, b: b, v: z, h: w, a: 1, c: 2}
It will throw error if e, b, z, w is not defined.
Values of objectA and objectB remain unchanged.
From extend({}, objectA, objectB), it gets the value from objectB to replace objectA, and then objectA to {} without changing the original value of objectA and objectB.
Note: You will need to change the keys in objectB to reflect keys in objectA instead of using 1, 2, 3... as keys.

Explanation for in loop JavaScript

Who can explain how this for in loop works and why it's assign keys of object to array
var o = {
a: 1,
b: 2,
c: 3,
d: 4
};
var a = [],
i = 0;
for (a[i++] in o);
console.log(a);
Using a side effect when enumerating the object, and using an empty statement, each key is stored in the array a; first key in a[0], next in a[1] etc.
It is not necessary however since you could just use Object.keys(o)
var o = {
a: 1,
b: 2,
c: 3,
d: 4
};
var a = [],
i = 0;
for (a[i++] in o); // do nothing loop
console.log(a,Object.keys(o));

two javascript syntax problem

These days I am reading some javascript source codes,however I found some syntax that I can not understand.
1)the for-in loop
var c;
var obj={name:'test',age:33};
for(var e in c={},obj){
console.info(e+' = '+obj[e]);
}
2)The Conditional Operator (?:)
Generally,we use this operator this manner:
x > 0 ? x*y : -x*y
But I have seen some codes like this:
x > 0 ? (x*y,z=bar,..other expressoin) : (-x*y)
But it does not work if I change the comma to colon,it will throw a error.
In both cases, the comma operator [MDN] is used:
You can use the comma operator when you want to include multiple expressions in a location that requires a single expression. The most common usage of this operator is to supply multiple parameters in a for loop.
And the specification:
11.14 Comma Operator ( , )
Syntax
Expression :
AssignmentExpression
Expression , AssignmentExpression
(...)
Semantics
The production Expression : Expression , AssignmentExpression is evaluated as follows:
Let lref be the result of evaluating Expression.
Call GetValue(lref).
Let rref be the result of evaluating AssignmentExpression.
Return GetValue(rref).
That just means that the result of the last expression is returned as result of the whole "list" of expressions.
In the examples you gave, it is used for its side effects [Wikipedia], namely evaluating every expression.
In general I'd say that this is not such a good style and, as you noticed, more difficult to understand.
for(var e in c={},obj)
is the same as
c = {};
for(var e in obj)
an does not seem to add any value. Even better would have been to just initialize c in the first line: var c = {};.
In case of the conditional operator: If x > 0 is true, then all the expressions are evaluated and the result of the last expression is returned. In this case, using a normal if statement would be better (easier to understand).
Here again, the comma operator and maybe even the conditional operator seems to be used solely because of their side effects: Normally the conditional operator is supposed to only return a value but not to execute arbitrary expressions (a single function call which returns a value might be an exception).
As the MDN documentation says, it is more commonly used in a for loop to initialize multiple variables:
for(var i = 0, l = array.length; i < l; i++)
In Javascript you can define variables like:
var obj1 = { a: 2, b: 4, c: 6};
var obj2 = { x: 1, y: 3, z: 5};
Or, you can comma-separate the declarations, like this:
var obj1 = { a: 2, b: 4, c: 6}, obj2 = { x: 1, y: 3, z: 5};
Now, a for in loop is normally something like:
for(var key in obj1) { console.log(key); }
But, if you comma-chain the part after 'in' it will allow it (just like when assigning), but will run the loop on the last object in the chain.
var key, obj1 = { a: 2, b: 4, c: 6}, obj2 = { x: 1, y: 3, z: 5};
// will output 'a', 'b' and 'c'
for(key in obj2, obj1) { console.log(key); }
// will output 'x', 'y' and 'z'
for(key in obj1, obj2) { console.log(key); }
This means you can assign values within the for in, and then do looping on another object.
var key, obj3; // obj3 === null
var obj1 = { a: 2, b: 4, c: 6}, obj2 = { x: 1, y: 3, z: 5};
// will output 'a', 'b' and 'c'
for(key in obj3 = { j: 9, k: 8, l: 7 }, obj1) { console.log(key); }
// obj 3 is now { j: 9, k: 8, l: 7 }
Okay, so now for the ternary operators. If the above makes sense, so should this.
Ternary operations are like if statements with a single line. You can't put semicolons in a line because then it becomes two or more lines. But putting () around comma-separated declarations then it is still considered one line.
So this is valid:
x > 0 ? a = 1 : a = 2;
And this is valid:
x > 0 ? (a = 1, b = 2) : (a = 2, b = 1);
But this is not, because the commas throw off the interpretation of the ternary:
x > 0 ? a = 1, b = 2 : a = 2, b = 1;
But I would not recommend setting values in a ternary, unless it looks something like:
a = x > 0 ? 1 : 2;
:)
The first? no idea. The second? It's just like your typical inline if except it executes multiple expressions rather than one
x > 0 ? (doThis(),doThat(),x=2) : (again(),another(),y=5);
Isn't the first one just an initializer?
var c;
var obj={name:'test',age:33};
for(var e in c=[], obj){
console.info(e + ' = ' + obj[e]);
c.push(e);
}
console.info(c);
Now, why you'd do it that way... I'm not sure.

Categories