Unordered Dictionary in Javascript - javascript

I would like to iterate through the key of an unordered dictionary in Javascript. I don't even know if it does exist or not.
At the moment I am having the following code :
var l = [5,3,2];
var unorderedDict = {};
for (var i=0; i<l.length; i++) {
unorderedDict[l[i]] = 'foo';
}
My dictionary will then be like : {2:'foo', 3:'foo', 5:'foo'} or in my case, I would like to keep the ordering of the initial list (so : {5:'foo', 3:'foo', 2:'foo'})
How can I achieve this ?

You cannot maintain order in object. If you want to maintain order use array:
var l = [5, 3, 2];
var val = ['foo', 'bar', 'baz'];
var unorderedDict = [];
// ^^
for (var i = 0; i < l.length; i++) {
unorderedDict[l[i]] = val[i];
}
// Iterate over array:
for (var i = 0; i < unorderedDict.length; i++) {
if (unorderedDict[i]) {
console.log(unorderedDict[i]);
}
}
EDIT
If you want the order to be the same as shown in l:
// Iterate over array:
for (var i=0; i<l.length; i++) {
console.log(unorderedDict[l[i]]);
}

Related

Javascript - count and remove from an object

I have an object with duplicate values and I want to count all those which have the same value and remove them.
var myArray = [{nr: 'bbc',}, {nr: 'bbc'}, {nr: 'bbc'}, {nr: ccc}];
from this array I want to create another array but remove the duplicated values and count them to be like this.
var myArray = [{nr: 'bbc',amount: 3}}, {nr: ccc,amount: 1}];
You could probably use a better format
var count = {};
for(var i = 0; i < myArray.length; ++i) {
if(typeof count[myArray[i].nr] == 'undefined') {
count[myArray[i].nr] = 0;
}
++count[myArray[i].nr];
}
and this wound yield somehing like:
count = {
bcc: 3,
ccc: 1
};
if you still need it with the structure you specified, then:
var newArray = [];
for(var k in count) {
newArray.push({
nr: k,
amount: count[k]
});
}
If you want the same structure, this will work for you
var newArray = [];
for (var i = 0; i < myArray.length; i++) {
var matched = false;
for (var j = 0; j < newArray.length; j++) {
if(myArray[i].nr === newArray[j].nr){
matched = true;
newArray[j].amount++;
break;
}
};
if(!matched)
newArray.push({nr:myArray[i].nr,amount:1});
};
console.log(newArray);

Add different value to the same object literal javascript

I have a piece of code to create an object literal array. The array is created from 2 other string array, one will become the object literal colHeads and the other array will be the data dataArr.
colHeads = [name, state]
dataArr = [John A. Smith,Joan B. Jones]
var temp = [];
var tempObj = {};
for (var i=0; i<colHeads.length; ++i) { // columns
var dataArr = colDatas[i].split(",");
for (var j = 0; j < dataArr.length; j++) { // data
tempObj[colHeads[i]] = dataArr[j];
}
temp.push(tempObj);
}
The final array should look like this:
var data = [
{name: 'John A. Smith', state: 'CA'},
{name: 'Joan B. Jones', state: 'NY'}
];
Problem here is according to this line tempObj[colHeads[i]] = dataArr[0]; The object literal would be replaced with the last entry in both arrays which make the result look like this:
var data = [
{name: 'Joan B. Jones', state: 'NY'},
{name: 'Joan B. Jones', state: 'NY'}
];
I'm new to javascript so I don't know much the syntax
First off, your loop is accessing the same dataArr index, it should be using j
tempObj[colHeads[i]] = dataArr[j];
Second, you are not constructing new tempObjs for each loop, so each item index shares the same tempObj which will end up leaving you with a list of the same exact object.
So far your code should look something more like this:
var temp = [];
for (var i=0; i<colHeads.length; ++i) { // columns
var tempObj = {};
var dataArr = colDatas[i].split(",");
for (var j = 0; j < dataArr.length; j++) { // data
tempObj[colHeads[j]] = dataArr[j];
}
temp.push(tempObj);
}
Lastly, You are only creating one tempObj for each column, rather than each row as you should be doing.
var temp = [];
var rowCount = colDatas[0].split(',').length;
for (var i = 0; i < rowCount; ++i) { // rows first
var tempObj = {};
for (var j = 0; j < colHeads.length; ++j) { // now columns
tempObj[colheads[j]] = colDatas[j].split(',')[i];
}
temp.push(tempObj);
}
Now, due to the way your colDatas object is set up, it requires you to split them for every loop which can become pretty costly, I suggest you find another way to store that so it can be better optimized.
Create new object in cycle (prepare arrays before it), like this:
for (var i=0; i<colHeads.length; ++i) {
var tmpObj = {};
tmpObj.name = colHeads[i];
tmpObj.state = colDatas[i]
result.push(tmpObj);
}

rearrange Array according to values order of another Array

I have two arrays like below
var arr = ["x", "y", "z", "a", "b", "c"];
var tgtArr = [{val:"a"}, {val:"b"}]; It does not need to be as lengthy as Array `arr`
This is what I have tried
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
for(var k = 0; k < tgtArr.length; k++){
dest[i] = dest[i] || [];
if(tgtArr[k].val == arr[i]){
dest[i] = arr[i];
}
}
}
console.log(dest);
My Expected output is (for above tgtArr value)
[{}, {}, {}, {val:"a"}, {val:"b"}, {}];
if tgtArr is empty Array
[{},{},{},{},{},{}]
Here is the fiddle. Any alternative for this, it seems not a good way to me as I am iterating through the entire array everytime.
Short:
var result = arr.map(function(x) {
return tgtArr.some(function(o) { return o.val == x; }) ? {val:x} : {};
});
This is more efficient:
var set = {};
tgtArr.forEach(function(obj, i) {
set[obj.val] = true;
});
var result = arr.map(function(x) {
return x in set ? {val:x} : {};
});
This is the same as Paul's answer, but with a loop instead of map. It collects the keys first based on the val property, then creates a new array either with empty objects if the key isn't in tgtArr, or copies a reference to the object from tgtArr if it is:
function newArray(arr, tgtArr) {
var keys = {},
i = tgtArr.length,
j = arr.length,
newArr = [];
// Get keys
while (i--) keys[tgtArr[i].val] = tgtArr[i];
// Make new array
while (j--) newArr[j] = arr[j] in keys? keys[arr[j]] : {};
return newArr;
}
It should be efficient as it only traverses each array once.
var dest = new Array(arr.length);
for(var i = 0; i < arr.length; i++){
dest[i] = {}
for(var k = 0; k < tgtArr.length; k++){
if(tgtArr[k].val == arr[i]){
dest[i] = tgtArr[k];
}
}
}
console.log(dest);
I like using map rather than loops for this kind of thing (Fiddle):
var result = arr.map(function(x) {
var match = tgtArr.filter(function(y) {
return y.val == x;
});
if (match.length == 1) return match[0];
else return {};
});
This is a possibly inefficient, in that it traverses tgtArr for every item in arr, so O(n*m). If needed, you could fix that by pre-processing tgtArr and converting it to a hash map (Fiddle). This way you've got an O(n+m) algorithm (traverse each array once):
var tgtMap = {};
tgtArr.forEach(function(x) { tgtMap[x.val] = x; })
var result = arr.map(function(x) {
var match = tgtMap[x];
return match || {};
});
var tmp = {};
for (var i = 0; i < tgtArr.length; i++) {
tmp[tgtArr[i].val] = i;
}
var dest = [];
for (var i = 0; i < arr.length; i++) {
var obj= tmp[arr[i]] === undefined ? {} : tgtArr[tmp[arr[i]]];
dest.push(obj);
}
DEMO

Use an array to check data

I have an array which im using to loop through divs i have stored in variables... but i want to use the values in the array as part of the variable names i wish to check.
Heres an example of what im trying to do:
var data_one = document.getElementById('test'),
data_two = document.getElementById('test2'),
array = ['one','two'];
for (var i = 0; i < array.length; i++) { //error on this line
if(parseInt(data_+array[i]) < 3){
//do something
}
}
But i get this error Uncaught ReferenceError: data_ is not defined
Is there a way to use the array values to act like the variable name some how?
What about:
var data = [
document.getElementById('test'),
document.getElementById('test2')
];
for (var i = 0; i < data.length; i++) {
if(parseInt(data[i]) < 3){
//do something
}
}
or with an object:
var data = {
'one': document.getElementById('test'),
'two': document.getElementById('test2')
};
for (var i in data) {
if(parseInt(data[i]) < 3){
//do something
}
}
Use eval which evaluates string as javascript code
var data_a = 12;
var b = "a";
alert("data_"+b); // alerts data_a
alert(eval("data_"+b)); // alerts 12
See http://jsfiddle.net/ftGhd/
var data_one = document.getElementById('test'),
data_two = document.getElementById('test2'),
array = ['one','two'];
for (var i = 0; i < array.length; i++) {
eval("var curr_array = data_"+array[i]);
if(parseInt(curr_array) < 3){
//do something
}
}

How to show a list or array into a tree structure in javascript?

I pass this list from python to javascript like this:
var string=["test_data/new_directory/ok.txt","test_data/reads_1.fq","test_data/test_ref.fa"];
I want output like this:
test_data
reads_1.fq
test_ref.fa
new_directory
ok.txt
Or also the output could be like this:
test_data
reads_1.fq
test_ref.fa
test_data/new_directory
ok.txt
I used split function to get a list with each file and directory like this:
var string=["test_data/new_directory/ok.txt","test_data/reads_1.fq","test_data/test_ref.fa"];
for(var i=0;i<string.length;i++){
var result = string[i].split('/');
console.log(result);
}
Output looks like this:
["test_data", "new_directory", "ok.txt"]
["test_data", "reads_1.fq"]
["test_data", "test_ref.fa"]
How can I convert into the format I showed above? Thanks
Sorry for being late to the party. I ran into a similar issue trying to break out a list of paths into a nested object. Here's a fiddle showing how I ended up doing it.
var list = [];
list.push("A/B/C");
list.push("A/B/D");
list.push("A/B/C");
list.push("B/D/E");
list.push("D/B/E");
list.push("A/D/C");
var data = [];
for(var i = 0 ; i< list.length; i++)
{
buildTree(list[i].split('/'),data);
}
debugger;
function buildTree(parts,treeNode) {
if(parts.length === 0)
{
return;
}
for(var i = 0 ; i < treeNode.length; i++)
{
if(parts[0] == treeNode[i].text)
{
buildTree(parts.splice(1,parts.length),treeNode[i].children);
return;
}
}
var newNode = {'text': parts[0] ,'children':[]};
treeNode.push(newNode);
buildTree(parts.splice(1,parts.length),newNode.children);
}
https://jsfiddle.net/z07q8omt/
That's certainly possible, but it requires recursion.
The first thing you'll want to do (as you've already figured out to do, in fact) is split on the slashes. We'll use map for simplicity:
paths = paths.map(function(path) { return path.split('/'); });
Now we'll want to convert this into an array of objects with name and children properties. This means we'll have to use recursion.
In this function, we'll do a first pass grouping them by their first element:
var items = [];
for(var i = 0, l = paths.length; i < l; i++) {
var path = paths[i];
var name = path[0];
var rest = path.slice(1);
var item = null;
for(var j = 0, m = items.length; j < m; j++) {
if(items[j].name === name) {
item = items[j];
break;
}
}
if(item === null) {
item = {name: name, children: []};
items.push(item);
}
if(rest.length > 0) {
item.children.push(rest);
}
}
Then we can recurse on all of these (assuming the function name we chose was structurize):
for(i = 0, l = items.length; i < l; i++) {
item = items[i];
item.children = structurize(item.children);
}
Now we've got a nice structure. We can then stringify it, again with a recursive function. Since the directory listing is just each item name followed by the indented directory contents listing, we can write that fairly easily:
function stringify(items) {
var lines = [];
for(var i = 0, l = items.length; i < l; i++) {
var item = items[i];
lines.push(item.name);
var subLines = stringify(item.children);
for(var j = 0, m = subLines.length; j < m; j++) {
lines.push(" " + subLines[j]);
}
}
return lines;
}
Then, to actually do it:
console.log(stringify(structurize(paths)).join("\n"));

Categories