Pardon for taking this possibly slightly off-topic, but is there a
reason why this code is not using maps á [tag : occurances]?
JS has some wonderful ways to manipulate maps like the above, which
would provide a natural way to map a key (tag) to a value (occurances).
Rewriting one of the functions using the getTags() feature, it might
look like this (untested):
config.macros.allTags.handler = function(place,macroName,params)
{
var tags = store.getTags();
var theDateList =
createTiddlyElement(place,"ul",null,null,null);
if(tags.length == 0)
createTiddlyElement(theDateList,"li",null,"listTitle",this.noTags);
for (var t in tags)
{
var theListItem
=createTiddlyElement(theDateList,"li",null,null,null);
var theTag = createTiddlyButton(theListItem,t + " (" +
tags[t] + ")",this.tooltip.format([t]),onClickTag);
theTag.setAttribute("tag",t);
}
}
The actual getTags() code might look like this:
// Return an array of all the tags in use. Each member of the array is
another array where [0] is the name of the tag and [1] is the number of
occurances
TiddlyWiki.prototype.getTags = function()
{
var results = {};
this.forEachTiddler(function(title,tiddler) {
for(var g=0; g<tiddler.tags.length; g++)
{
var tag = tiddler.tags[g];
var f = false;
if (results[c])
results[c]++;
else
results[c] = 1;
}
});
return results;
}
The above would of course require refactoring in all places where
getTags() is used, but it may be worth it. Or I'm missing something. :)
-Kalle.
Hi,
Pardon for taking this possibly slightly off-topic, but is there a
reason why this code is not using maps á [tag : occurances]?
The above would of course require refactoring in all places where
getTags() is used, but it may be worth it. Or I'm missing something. :)
-Kalle.
// Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurances
TiddlyWiki.prototype.getTags = function()
{
var tagCount = {};
this.forEachTiddler(function(title,tiddler) {
for(var g=0; g<tiddler.tags.length; g++)
{
var tag = tiddler.tags[g];
var n = tagCount[tag];
tagCount[tag] = 1+(n?n:0);
}
});
var results = [];
for(var tag in tagCount)
results.push([tag,tagCount[tag]]);
results.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
return results;
}
// Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurances
TiddlyWiki.prototype.getTags = function()
{
var tags = new MultiSet();
this.forEachTiddler(function(title,tiddler) {
for(var g=0; g<tiddler.tags.length; g++)
tags.add(tiddler.tags[g]);
});
var results = tags.toArray();
results.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
return results;
}
> Hey Kalle,
> I am not sure as to why we arent using maps for this, but I dont
> think its worth the change now. The benefits are minimal at best, and
> not only would all the macros in the core that use the getTags
> function have to be changed, but it would also break a lot of plugins
> out there. Considering that maintaining backwards compatibility is
> always a big priority, I would think this is a no go. But lets wait
> and see what Jeremy has to say.
Hrm, no, I think you're right on there. If a lot of plugins are using
getTags and the return value changes completely, it's definitely not
worth the trouble.
-Kalle.
Hi Saq,
as you mentioned the getTags function I had a more detailed look at the original function and noticed it is a quite "expensive" function (in terms of speed) because it involves three nested loops.
So we should optimize this first. One way to accomplish this is using a hash instead of an array to collect the result.
// Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurances
TiddlyWiki.prototype.getTags = function()
{
var tagCounts = this.getTagsCount();
var result = [];
for(var i in tagCounts)
result.push([i,tagCounts[i]]);
result.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
return result;
}
function MultiSet()
{
var items = {};
this.add = function(item)
{
var n = items[item];
items[item] = 1+(n?n:0);
};
this.toArray = function()
{
var result = [];
for(var i in items)
result.push([i,items[i]]);
return result;
};
};
With this new class the getTags function would look like this:
// Return an array of all the tags in use. Each member of the array is another array where [0] is the name of the tag and [1] is the number of occurancesTiddlyWiki.prototype.getTags = function()
{
var tags = new MultiSet();
this.forEachTiddler(function(title,tiddler) {
for(var g=0; g<tiddler.tags.length; g++)tags.add(tiddler.tags[g]);
});
var results = tags.toArray();
results.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
return results;
}
(all code is untested)
We may even consider introducing a new function (e.g.) TiddlyWiki.prototype.getTagsCount that returns the hash/map (as suggested). The getTags function would just call getTagsCount and does the conversion and sorting:
On Thu, 2006-08-24 at 13:54 +0200, Udo Borkowski wrote:
> Hi Kalle,
>
> because of compatibility issues it is not possible to change the
> signature of the TiddlyWiki.prototype.getTags and return a hash/map
> instead of the array (this would break all plugins currently using the
> function).
Yeah, I didn't quite realize that there were a lot of plugins using the
function out there. Now I know. :)
> Nevertheless it is possible to perform the optimization, and convert
> the map to an array (and sort it) before it is returned by getTags.
> (See my recent post that I send before reading your suggestion).
>
> We may even consider introducing a new function (e.g.)
> TiddlyWiki.prototype.getTagsCount that returns the hash/map (as
> suggested). The getTags function would just call getTagsCount and does
> the conversion and sorting:
I think that's a great idea (getTagsCount). It would let existing
plugins choose whether to convert to using getTagsCount which would be
more optimized, or choose to stay with the regular getTags.
-Kalle.
The refactoring discussion is cool, and I back Udo's suggestions.
Probably won't get this into beta 5 though.
Cheers
Jeremy
On 8/24/06, Kalle Alm <kall...@gmail.com> wrote:
>
--
Jeremy Ruston
mailto:jer...@osmosoft.com
http://www.tiddlywiki.com