JS Array "Length" with non-consecutive index/key - javascript

How do I get the number of elements in an array with non-consecutive numbers as keys?
var array = [];
array[5] = "something";
array[10] = "nothing":
expected:
number of elements in array = 2
actual:
instead I get the last number used as the "length", 11
I can figure out the way to do this by iterating through each element. Is there is better way to do this?

You may count non empty cells:
array.filter(function(e){return e!==undefined}).length

Sounds like what you actually want is a dictionary, not an array. Have you considered that as an alternative data structure?
How to do associative array/hashing in JavaScript
var myArray = {};
myArray["5"] = "something";
myArray["10"] = "nothing";
And to get the length you would want to write a quick function like the one shown here:
Length of a JavaScript object
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
var size = Object.size(myArray);
Or alternatively, even simpler (but not supported by IE8):
Object.keys(myArray).length

var array = [];
array[5] = "something";
array[10] = "nothing":
Your array in this case becomes :
[undefined,undefined,undefined,undefined,undefined,"something",undefined,undefined,undefined,undefined,"nothing"]
thats why the length is coming as 11. So ideally you should not set it like array[5] or array[10].
If you have variable keys, then you should use object
a = {};
a["5"] = "something";
a["10"] = "nothing"
Then a will look like {"5":"something","10":"nothing"}
Then you can calculate count as :
var elemCount = 0;
for(var key in a){
elemCount++;
}
Output:
elemCount = 2
Various other ways of getting length of keys in object:
How to efficiently count the number of keys/properties of an object in JavaScript?

var array= Array(5);
array[1] = 10;
array[3] = 3;
numberOfElements = 0;
for(var i =0; i<array.length; i++) {
if(array[i]!=undefined)
numberOfElements++;
}
alert(numberOfElements);

Related

How to create key value pair using two arrays in JavaScript?

I have two arrays, keys and commonkeys.
I want to create a key-value pair using these two arrays and the output should be like langKeys.
How to do that?
This is array one:
var keys=['en_US','es_ES', 'pt_PT','fr_FR','de_DE','ja_JP','it_IT']
This is array two:
var commonKeys=['en-*','es-*', 'pt-*','fr-*','de-*','ja-*','it-*', '*']
This is the output I need:
var langKeys = {
'en-*': 'en_US',
'es-*': 'es_ES',
'pt-*': 'pt_PT',
'fr-*': 'fr_FR',
'de-*': 'de_DE',
'ja-*': 'ja_JP',
'it-*': 'it_IT',
'*': 'en_US'
};
You can use map() function on one array and create your objects
var keys=['en_US','es_ES', 'pt_PT','fr_FR','de_DE','ja_JP','it_IT'];
var commonKeys=['en-*','es-*', 'pt-*','fr-*','de-*','ja-*','it-*', '*'];
var output = keys.map(function(obj,index){
var myobj = {};
myobj[commonKeys[index]] = obj;
return myobj;
});
console.log(output);
JavaScript is a very versatile language, so it is possible to do what you want in a number of ways. You could use a basic loop to iterate through the arrays, like this:
var keys=['en_US','es_ES', 'pt_PT','fr_FR','de_DE','ja_JP','it_IT']
var commonKeys=['en-*','es-*', 'pt-*','fr-*','de-*','ja-*','it-*', '*']
var i;
var currentKey;
var currentVal;
var result = {}
for (i = 0; i < keys.length; i++) {
currentKey = commonKeys[i];
currentVal = keys[i];
result[currentKey] = currentVal;
}
This example will work in all browsers.
ES6 update:
let commonKeys = ['en-*', 'es-*', 'pt-*', 'fr-*', 'de-*', 'ja-*', 'it-*', '*'];
let keys = ['en_US', 'es_ES', 'pt_PT', 'fr_FR', 'de_DE', 'ja_JP', 'it_IT', 'en_US'];
let zipArrays = (keysArray, valuesArray) => Object.fromEntries(keysArray.map((value, index) => [value, valuesArray[index]]));
let langKeys = zipArrays(commonKeys, keys);
console.log(langKeys);
// let langKeys = Object.fromEntries(commonKeys.map((val, ind) => [val, keys[ind]]));
What you want to achieve is to create an object from two arrays. The first array contains the values and the second array contains the properties names of the object.
As in javascript you can create new properties with variales, e.g.
objectName[expression] = value; // x = "age"; person[x] = 18,
you can simply do this:
var keys=['en_US','es_ES', 'pt_PT','fr_FR','de_DE','ja_JP','it_IT'];
var commonKeys=['en-*','es-*', 'pt-*','fr-*','de-*','ja-*','it-*', '*'];
var langKeys = {};
var i;
for (i=0; i < keys.length; i++) {
langKeys[commonKeys[i]] = keys[i];
}
EDIT
This will work only if both arrays have the same size (actually if keys is smaller or same size than commonKeys).
For the last element of langKeys in your example, you will have to add it manually after the loop.
What you wanted to achieve was maybe something more complicated, but then there is missing information in your question.
Try this may be it helps.
var langKeys = {};
var keys=['en_US','es_ES', 'pt_PT','fr_FR','de_DE','ja_JP','it_IT']
var commonKeys=['en-*','es-*', 'pt-*','fr-*','de-*','ja-*','it-*', '*']
function createArray(element, index, array) {
langKeys[element]= keys[index];
if(!keys[index]){
langKeys[element]= keys[index-(commonKeys.length-1)];
}
}
commonKeys.forEach(createArray);
console.info(langKeys);
Use a for loop to iterate through both of the arrays, and assign one to the other using array[i] where i is a variable representing the index position of the value.
var keys = ['en_US', 'es_ES', 'pt_PT', 'fr_FR', 'de_DE', 'ja_JP', 'it_IT'];
var commonKeys = ['en-*', 'es-*', 'pt-*', 'fr-*', 'de-*', 'ja-*', 'it-*', '*'];
var langKeys = {};
for (var i = 0; i < keys.length; i++) {
var commonkey = commonKeys[i];
langKeys[commonkey] = keys[i];
}
console.log(JSON.stringify(langKeys));
let keys = ['en_US', 'es_ES', 'pt_PT', 'fr_FR', 'de_DE', 'ja_JP', 'it_IT'];
let commonKeys = ['en-*', 'es-*', 'pt-*', 'fr-*', 'de-*', 'ja-*', 'it-*', '*'];
// declaration of empty object where we'll store the key:value
let result = {};
// iteration over first array to pick up the index number
for (let i in keys) {
// for educational purposes, showing the number stored in i (index)
console.log(`index number: ${i}`);
// filling the object with every element indicated by the index
// objects works in the basis of key:value so first position of the index(i)
// will be filled with the first position of the first array (keys) and the second array (commonKeys) and so on.
result[keys[i]] = commonKeys[i];
// keep in mind that for in will iterate through the whole array length
}
console.log(result);

Javascript - nested loops and indexes

I am trying to build an array that should look like this :
[
[{"name":"Mercury","index":0}],
[{"name":"Mercury","index":1},{"name":"Venus","index":1}],
[{"name":"Mercury","index":2},{"name":"Venus","index":2},{"name":"Earth","index":2}],
...
]
Each element is the concatenation of the previous and a new object, and all the indexes get updated to the latest value (e.g. Mercury's index is 0, then 1, etc.).
I have tried to build this array using the following code :
var b = [];
var buffer = [];
var names = ["Mercury","Venus","Earth"]
for (k=0;k<3;k++){
// This array is necessary because with real data there are multiple elements for each k
var a = [{"name":names[k],"index":0}];
buffer = buffer.concat(a);
// This is where the index of all the elements currently in the
// buffer (should) get(s) updated to the current k
for (n=0;n<buffer.length;n++){
buffer[n].index = k;
}
// Add the buffer to the final array
b.push(buffer);
}
console.log(b);
The final array (b) printed out to the console has the right number of objects in each element, but all the indexes everywhere are equal to the last value of k (2).
I don't understand why this is happening, and don't know how to fix it.
This is happening because every object in the inner array is actually the exact same object as the one stored in the previous outer array's entries - you're only storing references to the object, not copies. When you update the index in the object you're updating it everywhere.
To resolve this, you need to create new objects in each inner iteration, or use an object copying function such as ES6's Object.assign, jQuery's $.extend or Underscore's _.clone.
Here's a version that uses the first approach, and also uses two nested .map calls to produce both the inner (variable length) arrays and the outer array:
var names = ["Mercury","Venus","Earth"];
var b = names.map(function(_, index, a) {
return a.slice(0, index + 1).map(function(name) {
return {name: name, index: index};
});
});
or in ES6:
var names = ["Mercury","Venus","Earth"];
var b = names.map((_, index, a) => a.slice(0, index + 1).map(name => ({name, index})));
Try this:
var names = ["Mercury","Venus","Earth"];
var result = [];
for (var i=0; i<names.length; i++){
var _temp = [];
for(var j=0; j<=i; j++){
_temp.push({
name: names[j],
index:i
});
}
result.push(_temp);
}
console.log(result)
try this simple script:
var b = [];
var names = ["Mercury","Venus","Earth"];
for(var pos = 0; pos < names.length; pos++) {
var current = [];
for(var x = 0; x < pos+1; x++) {
current.push({"name": names[x], "index": pos});
}
b.push(current);
}

javascript array with numeric index without undefineds

suppose I do..
var arr = Array();
var i = 3333;
arr[i] = "something";
if you do a stringify of this array it will return a string with a whole bunch of undefined numeric entries for those entries whose index is less than 3333...
is there a way to make javascript not do this?
I know that I can use an object {} but I would rather not since I want to do array operations such as shift() etc which are not available for objects
If you create an array per the OP, it only has one member with a property name of "333" and a length of 334 because length is always set to be at least one greater than the highest index. e.g.
var a = new Array(1000);
has a length of 1000 and no members,
var a = [];
var a[999] = 'foo';
has a length of 1000 and one member with a property name of "999".
The speedy way to only get defined members is to use for..in:
function myStringifyArray(a) {
var s = [];
var re = /^\d+$/;
for (var p in a) {
if (a.hasOwnProperty(p) && re.test(p)) {
s.push(a[p]);
}
}
return '' + s;
}
Note that the members may be returned out of order. If that is an issue, you can use a for loop instead, but it will be slower for very sparse arrays:
function myStringifyArray(a) {
var s = [];
var re = /^\d+$/;
for (var i=0, iLen=a.length; i<iLen; i++) {
if (a.hasOwnProperty(i)) {
s.push(a[i]);
}
}
return '' + s;
}
In some older browsers, iterating over the array actually created the missing members, but I don't think that's in issue in modern browsers.
Please test the above thoroughly.
The literal representation of an array has to have all the items of the array, otherwise the 3334th item would not end up at index 3333.
You can replace all undefined values in the array with something else that you want to use as empty items:
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] == 'undefined') arr[i] = '';
}
Another alternative would be to build your own stringify method, that would create assignments instead of an array literal. I.e. instead of a format like this:
[0,undefined,undefined,undefined,4,undefined,6,7,undefined,9]
your method would create something like:
(function(){
var result = [];
result[0] = 0;
result[4] = 4;
result[6] = 6;
result[7] = 7;
result[9] = 9;
return result;
}())
However, a format like that is of course not compatible with JSON, if that is what you need.

slice string to pieces and store each in new array

Help needed.
I have string like ["wt=WLw","V5=9jCs","7W=71X","rZ=HRP9"] (unlimited number of pairs)
I need to make an array with pair like wT (as index) and WLw as value, for the whole string (or simpler wT as index0, WLw as index 1 and so on)
I'm trying to do it in JavaScript but I just cant figure out how to accomplish this task.
Much much appreciate your help!!
You cannot have a string as an index in an array, what you want is an object.
All you need to do is loop over your array, split each value into 2 items (key and value) then add them to an object.
Example:
// output is an object
var output = {};
var source = ["wt=WLw","V5=9jCs","7W=71X","rZ=HRP9"];
for (var index = 0; index < source.length; index++) {
var kvpair = source[index].split("=");
output[kvpair[0]] = kvpair[1];
}
If you wanted an array of arrays, then its much the same process, just pushing each pair to the output object
// output is a multidimensional array
var output = [];
var source = ["wt=WLw","V5=9jCs","7W=71X","rZ=HRP9"];
for (var index = 0; index < source.length; index++) {
output.push(source[index].split("="));
}
Update If your source is actually a string and not an array then you will have to do a little more splitting to get it to work
var output = {};
var sourceText = "[\"wt=WLw\",\"V5=9jCs\",\"7W=71X\",\"rZ=HRP9\"]";
// i have escaped the quotes in the above line purely to make my example work!
var source = sourceText.replace(/[\[\]]/g,"").split(",");
for (var index = 0; index < source.length; index++) {
var kvpair = source[index].split("=");
output[kvpair[0]] = kvpair[1];
}
Update 2
If your desired output is an array of arrays instead of an object containing key-value pairs then you will need to do something like #limelights answer.
Object with Key-Value pairs: var myObject = { "key1": "value1", "key2": "value2" };
with the above code you can access "value1" like this myObject["key1"] or myObject.key1
Array of Arrays: var myArray = [ [ "key1", "value1"] ,[ "key2", "value2" ] ];
with this code, you cannot access the data by "key" (without looping through the whole lot to find it first). in this form both "key1" and "value1" are actually values.
to get "value1" you would do myArray[0][1] or you could use an intermediary array to access the pair:
var pair = myArray[0];
> pair == ["key1", "value1"]
> pair[0] == "key1"
> pair[1] == "value1"
You can use a for each loop on both types of result
// array of arrays
var data = [ [ "hello", "world"], ["goodbye", "world"]];
data.forEach(function(item) {
console.log(item[0]+" "+item[1]);
});
> Hello World
> Goodbye World
// object (this one might not work very well though)
var data = { "hello": "world", "goodbye": "world" };
Object.keys(data).forEach(function(key) {
console.log(key+" "+data[key]);
});
> Hello World
> Goodbye World
The normal for loop would do perfectly here!
var list = ["wt=WLw","V5=9jCs","7W=71X","rZ=HRP9"];
var pairs = [];
for(var i = 0; i < list.length; i++){
pairs.push(list[i].split('='));
}
This would give you an array of pairs, which I assume you want.
Otherwise just get rid of the outer Array and do list[i].split('=');
If you want it put into an object ie. not an Array
var pairObject = {};
for(var i = 0; i < list.length; i++){
var pair = list[i].split('=');
pairObject[pair[0]] = pair[1];
}

JavaScript: convert objects to array of objects

I have thousands of legacy code that stores array information in a non array.
For example:
container.object1 = someobject;
container.object2 = someotherobject;
container.object3 = anotherone;
What I want to have is:
container.objects[1], container.objects[2], container.objects[3] etc.
The 'object' part of the name is constant. The number part is the position it should be in the array.
How do I do this?
Assuming that object1, object2, etc... are sequential (like an array), then you can just iterate through the container object and find all the sequential objectN properties that exist and add them to an array and stop the loop when one is missing.
container.objects = []; // init empty array
var i = 1;
while (container["object" + i]) {
container.objects.push(container["object" + i]);
i++;
}
If you want the first item object1 to be in the [1] spot instead of the more typical [0] spot in the array, then you need to put an empty object into the array's zeroth slot to start with since your example doesn't have an object0 item.
container.objects = [{}]; // init array with first item empty as an empty object
var i = 1;
while (container["object" + i]) {
container.objects.push(container["object" + i]);
i++;
}
An alternate way to do this is by using keys.
var unsorted = objectwithobjects;
var keys = Object.keys(unsorted);
var items = [];
for (var j=0; j < keys.length; j++) {
items[j] = unsorted[keys[j]];
}
You can add an if-statement to check if a key contains 'object' and only add an element to your entry in that case (if 'objectwithobjects' contains other keys you don't want).
That is pretty easy:
var c = { objects: [] };
for (var o in container) {
var n = o.match(/^object(\d+)$/);
if (n) c.objects[n[1]] = container[o];
}
Now c is your new container object, where c.object[1] == container.object1

Categories

Resources