I have class that can have nested same class instances:
class SomeClass
{
List<SomeClass> SomeClasses;
}
And... I need to know what is the most high amount in chain Parent - Children.
It's like that:
I so confused about this, so I don't even know how to start doing it. Most likely it can't be done without recursion.
Given that any SomeClass instance forms a tree, perhaps you are looking for the depth of the tree. If that's the case, you would indeed use recursion: write a function that accepts a SomeClass and returns 1 plus the maximum of the list formed by applying itself to the SomeClasses list.
Here for example is an implementation in JS:
const depth = ({ things }) => 1 + Math.max(0, ...things.map(depth))
depth({
things: [
{
things: [
{
things: []
},
{
things: [
{
things: []
}
]
}
]
}
]
});
// 4
Related
I need to implement a Tree data structure which should have multiple roots, not just 1 root. Look at this scenario, suppose I have to implement Tree data structure for "Book contents". Which are "Chapters > Sections > Sub-Sections" etc. The major problem is: There are multiple roots here, chapter 1, chapter 2, chapter 3 and so on. The root node must definitely start from chapters, since the type of content and functions are same starting from those level.
What my Task requires:
Tree with multiple roots
The Nodes are Ordered on horizontal level among same parent
It is a non-binary tree, meaning there can be any number of roots and any number of childs.
I have come with a solution, but I think it is a messy approach. I made one class like one would normally do for tree data structure. This class is "SimpleTree" which works for a single chapter as root node. To make multiple root nodes possible, I made another class "TopWrapperForSimpleTree". This top wrapper class has an Array in order to store multiple "SimpleTree" elements to it (Basically multiple roots). The messy part here is that I have to copy each function of "SimpleTree" and define it for the wrapper class as well. For example, a "Traversal Function" would traverse all the elements in the "SimpleTree". But now I have to implement a "Traversal Function" for "TopWrapperForSimpleTree" class as well where it would have to loop through all the Roots calling Traversal function on each of them and concatenating the result. The same goes for other functions like, finding a node, deleting a node etc.
To sum it all, I need a Tree Data structure which can have multiple roots. It should be ordered as well. The order is very important.
Image showing Tree with multiple roots
A "tree with multiple roots" is not a tree. When you consider each chapter to be a tree, then the collection of chapters is a forest. But you could just add a root node. Chapters belong to a Book, and the Book is then the root node.
You don't need a data structure for multiple roots. You need a data structure where nodes are multi-functional and can represent a book, a chapter, a section, ...etc without having to duplicate code. OOP is perfect for that (inheritance).
The idea is to define a class that has all the common features that all objects have in common. For instance, a book, a chapter, a section, ... all have a name, and they all can have "children". Iteration of a tree could be implemented as a method of this class.
Then a book would be an extension of this base class: a book can for instance have an author property. A section would also be an extension of the base class, but could have as extra property a page number. A chapter could be an extension of a section, as it also has a page number, but may in addition have a chapter number, ...etc.
Here is one of the many ways to do that. I use JavaScript here, but it works in a similar way in other OOP languages:
class Node {
constructor(name) {
this.name = name;
this.children = [];
}
add(...children) {
this.children.push(...children);
return this; // Return the instance, so method calls can be chained...
}
toString() {
return this.name;
}
* iter(depth=0) {
// A pre-order iteration through the whole tree that this node represents
yield [depth, this];
for (let child of this.children) {
yield * child.iter(depth+1);
}
}
* iterWithout(depth=0) {
// A pre-order iteration through the whole tree that this node represents
// ...but excluding the node on which the original call is made:
for (let child of this.children) {
yield [depth, child];
yield * child.iterWithout(depth+1);
}
}
}
class Book extends Node {
constructor(name, author) {
super(name);
this.author = author; // specific property for Book instance
}
toString() {
return super.toString() + ", by " + this.author;
}
}
class Section extends Node {
constructor(name, page) {
super(name);
this.page = page; // specific property for any section (also chapter)
}
toString() {
return super.toString() + ", page " + this.page;
}
}
class Chapter extends Section {
constructor(id, name, page) {
super(name, page);
this.id = id; // specific property for Chapter instance
}
toString() {
return "Chapter " + this.id + ". " + super.toString();
}
}
// Illustration of how it could be used:
function main() { // Demo
let book = new Book("The Perfect Theory", "Pedro G. Ferreira").add(
new Chapter(1, "If a Person Falls Freely", 1).add(
new Section("The Autumn of 1907", 1),
new Section("The Article in the Yearbook", 4),
new Section("Isaac Newton", 6),
new Section("Gravity", 9),
),
new Chapter(2, "The Most Valuable Discovery", 12),
new Chapter(3, "Correct Mathematics, Abominable Physics", 28),
new Chapter(4, "Collapsing Stars", 47)
);
for (let [depth, item] of book.iterWithout()) {
console.log(" ".repeat(depth) + item.toString());
}
}
main();
I'm trying to use the V4 API of GITHUB to get a list of my assigned issues along with its labels and references.
After some time I got the query you can see below, which works exactly how I want.
There is however, a problem: it includes a lot of empty nodes I am not interested at. For example, if I want to get all the CrossReferencedEvent that are issues I will get a lot of empty nodes on the timeline edges array because the other events: LabeledEvent, ReferencedEvent, AssignedEvent etc.
How can I filter out those so I only get the events I am interested at?
Is this a limitation of graphql? Am I forced to remove the useless nodes locally?
This is the query that I have currently
{
search(query: "assignee:danielo515", type: ISSUE, last: 100) {
edges {
node {
... on Issue {
number
title
state
timeline(first: 10) {
edges {
node {
... on CrossReferencedEvent {
source{
... on Issue {
title
number
}
}
}
}
}
}
labels(last: 10) {
nodes {
name
color
}
}
repository {
name
}
}
}
}
}
}
One improvement I can make is, on the query part add is:issue. This will . save me all the empty nodes at the root edges array, but I don't see how to do the same for the nested timeline.
Thanks in advance
Problem Description
I am writing a geb/spock spec which fetches test data from DB2 into a map (the map variable is called "preFilledFields" - see the "MySpec" class further down).
This map is then being iterated over, and for each iteration I check too see if the value matches one in a row on the page.
When I perform the assertion above accessing the module object attributes, then the average execution time per assertion is approx. 5-6 seconds. If I perform the assertion using selectors directly, then the average execution time per assertion is approx. 70-80 ms. See the "MyPage" class for more details regarding the assertions.
Does anyone know what could be the cause of this? Is the bad performance a result of my code, or is there a general problem with regards to performance when using modules in geb?
Appreciate any help and input I can get.
Code:
My "RowModule" class looks like this:
class RowModule extends Module {
static final PREDEFINED_ATTR = "data-predefined-amount"
static content = {
cell { $("td", it) }
description { cell(0).text() }
rubrikNum { cell(1).text().toInteger() }
preDefinedAmount { cell(0).parent("tr").$("td[$PREDEFINED_ATTR]").attr("$PREDEFINED_ATTR") }
inputField { cell(0).parent("tr").$("td input") ?: false }
dataType{ cell(0).parent("tr").attr("data-type") }
}
}
My Page class looks like this:
class MyPage extends Page {
static url = "<some_url>"
static at = { $("h1").text() == "<some_text>" }
static content = {
submitButton { $("input", name:"<some_name>") }
myPageItems {
$("table tr").collect { it.module(RowModule) }
}
}
void verifyPrePopulatedFields(name, amount) {
long now = System.currentTimeMillis();
assert amount == selvangivelseItems.find { it.dataType== name}.preDefinedAmount.toInteger()
//assert amount == $("tr[data-type='" + name+ "']").$(".skts-tooltip-holder").text().toInteger()
println "Execution time" + (System.currentTimeMillis() - now) + " ms"
}
void submit() { submitTaxReturnButton.click() }
}
My Spec file looks like this:
class MySpec extends GebReportingSpec {
#Unroll
def "field #name is pre-populated with amount #amount from the database"() {
expect:
page(MyPage) verifyPrePopulatedFields(name, amount)
where:
name << preFilledFields.keySet()
amount << preFilledFields.values()
}
}
There are no general performance problems with using modules in Geb, at least none that I know of. Your selectors on the other hand are definitely suboptimal.
Firstly by doing myPageItems.find { it.dataType == name } you are iterating over all rows in your table and executing 3 WebDriver commands (that is http request between your test and the browser that is being driven) for each of them. You could improve the selector for dataType to dataType { attr("data-type") } (not 100% sure here because I don't see your DOM structure but this is what logic would suggest) but it would still mean potentially making a lot of requests. You should instead add a site content definition like this:
myItem { dataType ->
$("table tr[data-type='$dataType']").module(RowModule)
}
And then use it like:
assert amount == myPageItem(name).preDefinedAmount.toInteger()
Secondly you can simplify and improve performance of your selectors in the module (if my assumptions about your DOM are correct):
static content = {
cell { $("td", it) }
description { cell(0).text() }
rubrikNum { cell(1).text().toInteger() }
preDefinedAmount { $("td[$PREDEFINED_ATTR]").attr("$PREDEFINED_ATTR") }
inputField { $("td input") ?: false }
dataType{ attr("data-type") }
}
You should avoid using multiple selectors for things that can be found using a single selector or using unnecessary selectors because they will always carry a performance penalty.
The d3.js expression
d3.select(foo).selectAll(some_selector)
will return a selection comprising all the strict descendants of foo that satisfy some_selector.
But suppose that foo itself satisfies some_selector. How can I get it included in the resulting selection when this is the case?
The following naive solution to this problem
d3.select(foo.parentNode).selectAll(some_selector)
is incorrect, because, in general, the selection resulting from it will include any siblings of foo that satisfy some_selector!
IOW, I'm looking for a solution that is clearer, more concise, and less of a dirty hack than this (for example):
// temporarily tag all candidate elements, namely, foo and all its descendants
d3.select(foo).classed('yuk', true)
.selectAll('*').classed('yuk', true);
var parent = d3.select(foo.parentNode),
wanted = parent.selectAll(some_selector)
.filter('.yuk');
// undo the tagging
parent.selectAll('.yuk').classed('yuk', false);
Your question addresses the same issue as the other one you posted yesterday, although not being an exact duplicate. My answer to that one will work for this problem as well. I have adjusted my JSFiddle to allow for some filtering on the node and its descendants:
var selector = ".foo",
x = d3.select("#x"); // your parent node
// Get all children of node x regarding selector as NodeList and convert to Array.
var xAndDescendants = Array.prototype.slice.call(
x.node().querySelectorAll(selector)
);
// Add node x to the beginning if selector is true.
if (!(x = x.filter(selector)).empty())
xAndDescendants.unshift(x.node());
// Select resulting array via d3.js
var selection = d3.selectAll(xAndDescendants);
It's possible to avoid the class but its a bit complicated.
Here is one solution (I'm sure there are simpler ways!)..
function init() {
d3.select(foo)
.selectAll('*')
.call(function () {
immediateFamily(this, function (selection) {
return selection
.style('padding', '3px')
.style('border', '1px solid green')
})
})
}
;(function () {
$(document).ready(init)
})()
function immediateFamily(selection, styling) {
styling(selection)
styling(d3.select(selection[0].parentNode))
}
The idea is to avoid repeating the styling clauses by putting them in an anonymous function in the selection chain and pass this, along with the this context, to a function that applies said styling to the the selection and the parent node of the first group in the selection.
To make it slightly more terse - and even less comprehensible...
function immediateFamily2(selection, styling) {
styling(d3.select(styling(selection)[0].parentNode))
}
To take it to it's ultimate and possibly most idiomatically correct conclusion...
;(function () {
$(document).ready(init2)
function init2() {
var foo = d3.select('tr').filter(':first-child')[0][0]
d3.select(foo)
.selectAll('*')
.call(immediateFamily, bar)
function bar(selection) {
selection
.style('margin', '10px 20px 10px 20px')
.style('outline', '1px solid green')
}
}
function immediateFamily(selection, styling) {
styling(this)
styling(d3.select(this[0].parentNode))
return this
}
})()
Of course it could be further generalised but you get the idea.
(This code runs fine, but feel free to insert your own semicolons!)
I have a list of pairs with class inheritance information like this
[
[Person, null],
[Person, SpecialPerson], // Person extends SpecialPerson
[SpecialPerson, VerySpecialPerson], // SpecialPerson extends VerySpecialPerson
]
Is there any particular algorithm to flatten this information?
Like this:
Person -> SpecialPerson -> VerySpecialPerson
In the end, it boils down to a DAG (directed acyclic graph). Therefore you would do a breadth-first search or depth-first search. You only need the simplified case for trees.
Example (BFS, pseudo-code, untested):
List<Array<Typespec>> flatten(Array<Pair<Typespec,Typespec>> input) {
List<Array<Typespec>> result;
Queue<Array<Typespec>*> q;
var elem=&result.append([null]);
q.append(elem);
while (!q.empty()) {
for (i in input) {
if (i.first==q.front().back()) {
var elem=&result.append(q.front().clone().append(i.second));
q.append(elem);
}
}
q.pop_front();
}
return result;
}
This assumes that you meant [null,Person], instead of the other way round. Note that it produces a null at the start of every result, differing from your example.