Если вы хотите, чтобы узлы соответствовали большим ярлыкам, вы можете использовать свойство getBBox текстового узла SVG после того, как вы его нарисовали. Вот как я это сделал, для списка узлов с фиксированными координатами и двух возможных фигур:
nodes.forEach(function(v) {
var nd;
var cx = v.coord[0];
var cy = v.coord[1];
switch (v.shape) {
case "circle":
nd = svg.append("circle");
break;
case "rectangle":
nd = svg.append("rect");
break;
}
var w = 10;
var h = 10;
if (v.label != "") {
var lText = svg.append("text");
lText.attr("x", cx)
.attr("y", cy + 5)
.attr("class", "labelText")
.text(v.label);
var bbox = lText.node().getBBox();
w = Math.max(w,bbox.width);
h = Math.max(h,bbox.height);
}
var pad = 4;
switch (v.shape) {
case "circle":
nd.attr("cx", cx)
.attr("cy", cy)
.attr("r", Math.sqrt(w*w + h*h)/2 + pad);
break;
case "rectangle":
nd.attr("x", cx - w/2 - pad)
.attr("y", cy - h/2 - pad)
.attr("width", w + 2*pad)
.attr("height", h + 2*pad);
break;
}
});
Обратите внимание, что форма добавлена, текст добавлен, , затем форма позиционируется, чтобы текст отображался сверху.
Я согласен, что O(N)
- лучшее, что вы можете сделать.
Я сделал упрощение для вашей программы. Вам не нужно использовать исключение try и raise здесь.
input_string = "foobaarfoooobaaaarfo"
count_dict = {}
for char in input_string:
count_dict[char] = count_dict.get(char, 0) + 1
print(count_dict)