How do I add the value of an array to an object - javascript

I've got code which splits the key and value at the = sign at end if line, the problem is that I have lines which have more then one =
For example:
user = aaaa
userb = bbbb
userc = test
userd = foo = bar = test
I read file with node fs and I divide it to the key and value at the = so userd causes a problem.
I am using var array = line.split('=');
Then I assign it to object in the loop
myobj = {}
myobj[array[0]] = array[1];
This is working (my obj in the loop contains all the users) until I get to userD.
So how can I concatenate all the values of userD to myObj

If we assume that everything after the first = sign is the value, regardless of whether theres another = sign then you can do this:
myobj[array[0]] = array.slice(1).join(' = ');
Now, if you want to store it simple as an array of equal values, you can do:
myobj[array[0]] = array.slice(1);
The slice function returns the same array starting at the element passed (it does more but thats what it's for here).
Update I didn't think of this answer but it's even a bit faster!

Have a look at Array.prototype.shift():
myobj[array.shift()] = array;
Unlike Array.prototype.splice(), shift() won't create an entirely new array in order to wrap up the one value we're trying to extract. See my comment here.
Here are the results from a performance test; it shows operations per second (higher is better):
UserAgent shift slice splice
Chrome 44.0.2403 4,290,938 3,993,798 1,042,423
Chrome 46.0.2468 3,631,277 4,020,712 1,098,866
Firefox 38.0 1,706,068 1,419,219 895,714
Firefox 40.0 1,739,110 1,508,623 955,794
IE 11 in Compatibility Mode 10.0.0 3,393,698 2,855,417 1,721,229
Total 14,761,091 13,797,769 5,714,026
According to these results, shift() is the fastest with slice() right behind. splice(), on the other hand, is a good bit slower than both... mainly because it's ill-suited to this particular task.
That said, I was surprised. I expected this answer to be the fastest.

Use splice function:
myobj[array.splice(0, 1)] = array;
This will cut the first item out of your array and return it as myobj parameter, the rest is going to be kept in the array, so you can either use array as an object property or let's say join it to a string:
myobj[array.splice(0, 1)] = array.join(", ");

Related

Forcing string representation of an array key

I am trying to maintain the order of an array with mixed key types. The array contains mostly keys represented by string values -- but if you enter a numbered key it goes to the front. How can I force a key which is a number to be a string type?
E.g.
array = [];
array["one"] = "some data";
array["two"] = "some more data";
array["3"] = "this should not be the first element";
How can I make "3" a string type to prevent it from moving to the top of the index?
Oh wow did you ever open multiple cans of worms.
Javascript arrays are a special type of Javascript objects, and like all Javascript objects they can have arbitrary string properties:
const foo = [];
foo["bar"] = "hi";
However that string is a property of the array object, not an item in the array:
foo.forEach(console.log); // logs nothing
You can still access it like any other object property:
console.log(foo["bar"]); // "hi"
But it won't show up in the usual iterative constructs like c-style for loops or the map/forEach array methods.
The line in your example
array["3"] = "this should not be the first element";
is very different however, because of Javascript's playing fast and loose with type conversions this actually sets the string to the 4th slot in the array:
const bar = [];
bar["3"] = "oops!"; // equivalent to bar[3] = "oops!"
console.log(bar); // [empty x 3, "oops!"]
This piece of it is actually a good thing (other than the implicit conversion part) rather than a problem: sometimes you need a sparse array and JS supports those. Iterating it will only produce the one element:
bar.forEach((item, index) => console.log(item, index)); // ["oops", 3]
Note though that the string has the correct index of 3, and can be accessed that way even though there's nothing "in front" of it:
bar[3]; // "oops"
So the first two assignments in your example create properties on the array object, and the third assignment is the only one that actually adds an item to the array, at the 4th index (there's nothing at the first 3).
What you seem to want as Reese Casey suggests, is a plain object:
const foo = {}; // curly
foo["some string"] = "whatever";
However now the properties are basically unordered. If you want them to be in a guaranteed specific order you do want an array, but all your indicies will need to be integers, and should be sequential. You can achieve this easily by using the .push method:
foo = [];
foo.push("something");
foo.push("something else");
Now foo will have two elements, in the correct order, and index 0 and 1 respectively.
Update based on comment on the other answer:
I want some of the data to be ordered, and the rest of the data to follow
This can be accomplished through object destructuring:
const responseFromDB = {
oneKeyICareAbout: 3,
anotherKeyICareAbout: 2,
foo: 6,
bar: 7,
};
const {
oneKeyICareAbout,
anotherKeyICareAbout,
*rest,
} = responseFromDB;
const stuffToDisplay = [
oneKeyICareAbout,
anotherKeyICareAbout,
...Object.values(rest),
]; // [3, 2, 6, 7]
And at least the destructured stuff you put in the array will be ordered because by doing so you've ordered it.
Javascript arrays cannot have string indexes. This is actually working incorrectly as the index is adding a property to the array object.
Changing to an object makes more sense for this.
EDIT: Whilst below its mentioned you can have string indexes you are not actually using the array by doing so. The answer by Jared Smith goes into much more detail as to why.
The other answers explain what is happening with your array-object mixture. For having an indexable thing which can reproduce the original order, you can use a Map:
The Map object holds key-value pairs and remembers the original insertion order of the keys.
array = new Map();
array.set("one","some data");
array.set("two","some more data");
array.set("3","this should not be the first element");
console.log("Test of get:",array.get("two"));
console.log("Test of order:");
for(let entry of array)
console.log(entry);

Storing the word length in javascript array

I am puzzled as to why I can not store the word length in a javascript array.
I have tried
var i = [];
i["length"] = "ABC";
i["len"+"gth"] = "ABC";
but both aren't accepted in javascript. Can anyone explain it, and is there a way that I can store the word length in an array as above.
Since some asked for more detail. I am creating a list of words that I need to do a lookup at and find the value to display to the user. My list contains for example:
localVars.FunctionDic = [];
localVars.FunctionDic["lastindexof"] = "LastIndexOf(text, textToLocate)";
localVars.FunctionDic["specificindexof"] = "SpecificIndexOf(text, textToLocate, indexNumber)";
localVars.FunctionDic["empty"] = "Empty(text)";
localVars.FunctionDic["length"] = "Length(text)";
everything works except for the "length"
and I am using an array since I need to test if the word a user search for is in my array, and if it is display the value, if it is not, show nothing
It does not work because you are trying to write a string to a property that only allows a number.
From MDN: The length property of an object which is an instance of type Array sets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.
With the limited details in your question it is hard to tell what you are actually trying to accomplish. It seems like you want to use an array like an object. If that is the case, use an object.
var i = {};
i["length"] = "ABC";
Based on the expected output, I believe you should be using an object not an array.
const FunctionDic = {
lastindexof: "LastIndexOf(text, textToLocate)",
specificindexof: "SpecificIndexOf(text, textToLocate, indexNumber)",
empty: "Empty(text)",
length: "Length(text)",
};
console.log(FunctionDic["lastindexof"]);
console.log(FunctionDic["specificindexof"]);
console.log(FunctionDic["empty"]);
console.log(FunctionDic["length"]);
To store the word length in an array you can do:
var i = ["length"]
If you want to store the length of a word in an array you can do:
var lengthOfHello = "hello".length
var i = [lengthOfHello]
var i = ["ABC"];
console.log(new Array(i[0].length).length);

Node.JS behaves strange

I have a variable called uids
var uids = [];
Then I write some value to it property
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509"
But before it
if (!uids[user.id]) {
uids[user.id] = generateKey(user);
}
This thing behaves ok. If I try to get the value of it property
uids[currentUser.id]
It will give me a value of this property. If I try to call some methods like
Object.keys(uids);
It will give me, what I expected. And here the mystery comes...
uids;
RAM rest in piece. See the node eating ram
I am very confused now. What's wrong?
This is because you are creating a huge array and node will reserve memory for it - who knows what comes. I'd say that's a scenario where you would use a Map (or a plain object, but Map feels better here.
var uids = new Map();
var key = 456464564564654;
if (! uids.has(key)) {
uids.set(key, generateKey(user))
}
You are creating an empty array (length is zero), then you assign some value to an arbitrary index. This will make the array grow as big as the index and assign the value to that index. Look at this example using node.js REPL:
> var a = []
undefined
> a[5] = "something"
'something'
> a
[ , , , , , 'something' ]
> a.length
6
Instead of creating an array, you could create a Map() or an common javascript object (singleton). Javascript objects behave like Maps but only Strings can be used as keys. If you assign a Number to be key, javascript will convert it to String automatically.
Personally, I would go with objects because they perform better. Instantiating an object takes longer than instantiating a Map (and it doesn't seem like you need to create several groups of "uids"), but once done, adding new keys and retrieving values from any key in faster when using common objects. At least that's how things go in my node.js v6.7.0 on ubuntu 14.04 but you could try for yourself. And it would also make the least alteration to your code.
var uids = {} // common/ordinary empty javascript object instead of array.
if (!uids[user.id]) { // getting value from one key works the same.
uids[user.id] = generateKey(user) // assignment works the same.
}
////
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509" // key will be "16778923".
uids[16778923] // getting value for key "16778923" can be done using 16778923 instead of "16778923".
////
uids[currentUser.id] // still returning values like this.
Object.keys(uids) // still returning an array of keys like this. but they are all Strings.

Javascript: Calling a function in an object literal

I'm learning to program in Javascript and I'd like some help/clarification.
I declared an array that contains animal names. I defined a function that I use to split a string in two. Then I create an empty object literal and add an animal and corresponding breed. I'm trying to invoke the separateWords function in the object literal, but I need some clarification. Here's my code:
var myPets = ["Bengal Bobcat", "Beagle"];
var separateWords = function (string) {
return string.split(" ");
};
var nameCollection = {};
nameCollection.cat = separateWords(myPets[0]);
nameCollection.dog = myPets[1];
nameCollection.fish = null;
When I enter console.log(nameCollection) I get the following:
Object {cat: Array[2], dog: “Beagle”, fish: null}
cat: Array[2]
0: "Bengal"
1: "Bobcat"
length: 2
However, when I enter console.log( separateWords(myPets[0])), I see:
[“Bengal”, “Bobcat”]
I don’t understand why the value of cat shows up as Array[2].
The console displays it as Array[2] as it would be (potentially) unreadable if it expanded it fully. One way to see everything is to stringify it using JSON.stringify which goes through each item in the object recursively and calls toString() on it:
var myPets = ["Bengal Bobcat", "Beagle"];
var separateWords = function (string) {
return string.split(" ");
};
var nameCollection = {};
nameCollection.cat = separateWords(myPets[0]);
nameCollection.dog = myPets[1];
nameCollection.fish = null;
document.body.textContent = JSON.stringify(nameCollection);
You are assigning to cat the result of the separateWords() function call, passing myPets[0] as a parameter.
separateWords() returns an array and with the myPets[0] input it returns a new array with the "Bengal" and "Bobcat" values splitted by the whitespace.
The split() function is the one creating an array with the splitted values and this result is returned by your separateWords() function, which also is the value assigned to the cat object member.
Each browser implements its console like it wants.
So your browser decided to implement the behavior you describe.
If you don't like it, propose a better idea to the developers of this browser. Or use another browser.
I am going to assume you are using Chrome Developer Tools or Firebug.
Developer tools condenses arrays and objects into easily readable lines you then inspect further with. What I mean is, you push the little arrow next each line in the console log to further inspect each object. I will use pictures to explain this.
Here I am assigning an array and then assigning an element in an object to that array as so:
As you can see when I log the object it show's an Array[2] rather than expand the array. In this next picture I then expand the array to inspect it.
Why is this exactly? My first thought is ease of readability. If you have an app that is complex and you have numerous debugging console logs, you can see all the logs on single lines making it easier to hunt down specific logs. As well, if you have a very large and complex object, it is arguably easier to read all the root elements on each line without expanding all the objects and arrays found within that object recursively.
String.prototype.split() returns an array containing the two values in the string which have been split. Read through this.
nameCollection.cat = separateWords(myPets[0])[0]; // nameCollection.cat == Bengal
nameCollection.cat = separateWords(myPets[0])[1]; // nameCollection.cat == Bobcat
This is simply how javascript (and many other languages) work. When you try to print "nameCollection" javascript doesn't automatically do a nice job of printing the cat array. Instead, it simply prints some type related information, which in this case is saying "cat" is an array of length 2.

producing a word from a string in javascript

I have a string which is name=noazet difficulty=easy and I want to produce the two words noazet and easy. How can I do this in JavaScript?
I tried var s = word.split("=");
but it doesn't give me what I want .
In this case, you can do it with that split:
var s = "name=noazet difficulty=easy";
var arr = s.split('=');
var name = arr[0]; //= "name"
var easy = arr[2]; //= "easy"
here, s.split('=') returns an array:
["name","noazet difficulty","easy"]
you can try following code:
word.split(' ').map(function(part){return part.split('=')[1];});
it will return an array of two elements, first of which is name ("noazet") and second is difficulty ("easy"):
["noazet", "easy"]
word.split("=") will give you an array of strings which are created by cutting the input along the "=" character, in your case:
results = [name,noazet,difficulty,easy]
if you want to access noazet and easy, these are indices 1 and 3, ie.
results[1] //which is "noazet"
(EDIT: if you have a space in your input, as it just appeared in your edit, then you need to split by an empty string first - " ")
Based on your data structure, I'd expect the desired data to be always available in the odd numbered indices - but first of all I'd advise using a different data representation. Where is this string word coming from, user input?
Just as an aside, a better idea than making an array out of your input might be to map it into an object. For example:
var s = "name=noazet difficulty=easy";
var obj = s.split(" ").reduce(function(c,n) {
var a = n.split("=");
c[a[0]] = a[1];
return c;
}, {});
This will give you an object that looks like this:
{
name: "noazert",
difficulty: "easy"
}
Which makes getting the right values really easy:
var difficulty = obj.difficulty; // or obj["difficulty"];
And this is more robust since you don't need to hard code array indexes or worry about what happens if you set an input string where the keys are reversed, for example:
var s = "difficulty=easy name=noazet";
Will produce an equivalent object, but would break your code if you hard coded array indexes.
You may be able to get away with splitting it twice: first on spaces, then on equals signs. This would be one way to do that:
function parsePairs(s) {
return s.split(' ').reduce(
function (dict, pair) {
var parts = pair.split('=');
dict[parts[0]] = parts.slice(1).join('=');
return dict;
},
{}
);
}
This gets you an object with keys equal to the first part of each pair (before the =), and values equal to the second part of each pair (after the =). If a string has multiple equal signs, only the first one is used to obtain the key; the rest become part of the value. For your example, it returns {"name":"noazet", "difficulty":"hard"}. From there, getting the values is easy.
The magic happens in the Array.prototype.reduce callback. We've used String.prototype.split to get each name=value pair already, so we split that on equal signs. The first string from the split becomes the key, and then we join the rest of the parts with an = sign. That way, everything after the first = gets included in the value; if we didn't do that, then an = in the value would get cut off, as would everything after it.
Depending on the browsers you need to support, you may have to polyfill Array.prototype.reduce, but polyfills for that are everywhere.

Categories

Resources