Hi,
is it possible to perform a std::sort on a ValueTree?
I got std::find_if to work with a Valuetree, but not std::sort. Is this possible? would be really cool, if not, are there any easy examples for juce::ValueTree::sort ?
Best,
equinox
Hi,
is it possible to perform a std::sort on a ValueTree?
I got std::find_if to work with a Valuetree, but not std::sort. Is this possible? would be really cool, if not, are there any easy examples for juce::ValueTree::sort ?
Best,
equinox
ValueTree features a sort function.
Since ValueTree has begin() and end() iterators I quickly threw a std::sort at it, but the Iterators seemed not to work with std::sort. But could have been my fault)
int main (int argc, char* argv[])
{
juce::ValueTree tree {"Parent", {},
{
{"Node",{{"text", "Ape"}}},
{"Node",{{"text", "Zebra"}}},
{"Node",{{"text", "Elephant"}}}
}};
DBG (tree.toXmlString());
struct Sorter
{
int compareElements (const juce::ValueTree& first, const juce::ValueTree& second)
{
return first.getProperty ("text").toString().compare (second.getProperty ("text").toString());
}
};
Sorter sorter;
tree.sort (sorter, nullptr, false);
// but this didn't compile here:
// std::sort (tree.begin(), tree.end(), [](const auto& first, const auto& second)
// {
// return first.getProperty ("text").toString().compare (second.getProperty ("text").toString());
// });
DBG ("sorted:");
DBG (tree.toXmlString());
return 0;
}
But the sorter approach did the job
std::sort requires that the iterator type is a ‘legacy random-access iterator’, but ValueTree::Iterator is only a ‘legacy forward iterator’. Therefore, std::sort should not be expected to work with ValueTree iterators.
Thanks for the example!
Sorter sorter;
tree.sort (sorter, nullptr, false);
Could also be
tree.sort (Sorter(), nullptr, false);
But still longer than some modern std::sort stuff
Thanks for the info! Ok, is there any chance that the iterator will be updated (if this is possible at all?).
Otherwise it would be also cool, if juce::ValueTree::sort() would just take some lamdba function.
I don’t think we have any plans in this area at the moment.
Ok, sad to hear.
would be really cool if it would be possible to shortn up those ~8 lines above to:
tree.sort([](const juce::ValueTree& first, const juce::ValueTree& second)
{ return first.getProperty("text").toString().compare(second.getProperty("text").toString()); }, nullptr, false);
But anyway I’m glad that there is also a solution right now.
It is possible, with a little helper:
template<typename T>
struct LambdaSorter
{
LambdaSorter (std::function<int(const T&, const T&)> s) : sortFunc (s) {}
int compareElements (const T& first, const T& second)
{
return sortFunc (first, second);
}
private:
std::function<int(const T&, const T&)> sortFunc;
};
int main (int argc, char* argv[])
{
juce::ValueTree tree {"Parent", {},
{
{"Node",{{"text", "Ape"}}},
{"Node",{{"text", "Zebra"}}},
{"Node",{{"text", "Elephant"}}}
}};
LambdaSorter<juce::ValueTree> sorter ([](const auto& first, const auto& second)
{
return first.getProperty ("text").toString().compare (second.getProperty ("text").toString());
});
tree.sort (sorter, nullptr, false);
DBG ("sorted:");
DBG (tree.toXmlString());
return 0;
}
Your idea to build in place doesn’t compile btw, because the ElementComparator is taken by reference…
Since the sort function is bespoke to the ValueTree you might save the hassle of templating as well…
Might be a trivial addition to the ValueTree as well, if the juce team wants to add that
Cool thanks for your help! With your helper I was able to produce a compiling one-liner ![]()
Helper:
struct LambdaSorter
{
using Vt = juce::ValueTree;
LambdaSorter(std::function<int(const Vt&, const Vt&)> s) : sortFunc(s) {}
int compareElements(const Vt& a, const Vt& b)
{
return sortFunc(a, b);
}
private:
std::function<int(const Vt&, const Vt&)> sortFunc;
};
Example with one-liner:
juce::ValueTree tree{ "Parent",
{},
{ { "Node", { { "text", "Ape" } } },
{ "Node", { { "text", "Zebra" } } },
{ "Node", { { "text", "Elephant" } } } } };
DBG(tree.toXmlString());
tree.sort(LambdaSorter ([](const auto& first, const auto& second) {
return first.getProperty("text").toString().compare(second.getProperty("text").toString()); }),
nullptr, false);
DBG("sorted:");
DBG(tree.toXmlString());
The Sorted() compiled also on my machine
I just cleaned it up a bit and send it to JUCE:
Let’s see where it ends up
cool! ![]()
Little bump, now that the ADC dust has settled…
Just bumping…
Seems never a convenient time, but
“Summer is the time when it is too hot to do the job that it was too cold to do last winter” – Mark Twain
I think it still would be really cool to implement modern things in e.g. ValueTree, so that we can move std erase remove idiom and all this nice stuff…