Suppose I have a global dict parent that contains some child like
parent = Dict( child1, child2, ...);
And each child is another dict of
child = Dict("weight" => 100.0; "height" = 10.0);
Is there a way to sort these childs in the parent respect to some category? Like I want to product a parent which has the child nodes sorted according to their weight?
Thanks,
So,
sort!(parent,by=x->x["weight"])
should do the trick. Use sort (no !) to return a new vector. Try ?sort in REPL for more options.
Related
Assume u have the following recursive record type
type Parent = {
Name : string
Age : int
Children : Child list }
and Child = {
Name : string
Parent : Parent option }
I can easily create instances with
module Builder =
let create name kids =
let rec makeChild kid = { kid with Parent = parent |> Some }
and parent =
{
Name = name
Age = 42
Children = children
}
and children = kids |> List.map makeChild
parent
let createChild name =
{ Child.Name = name; Parent = None }
But when i try to "transform" an existing adult into a parent using "with" like that:
module Builder2 =
let createAdult name age =
{ Parent.Name = name; Age = age; Children = [] }
let create name kids =
let rec makeChild kid = { kid with Parent = parent |> Some }
and parent =
{ (createAdult name 42) with
Children = children
}
and children = kids |> List.map makeChild
parent
let createChild name =
{ Child.Name = name; Parent = None }
I get:
error FS0040: This and other recursive references to the object(s) being defined will be checked for initialization-soundness at runtime through the use of a delayed reference. This is because you are defining one or more recursive objects, rather than recursive functions. This warning may be suppressed by using '#nowarn "40"' or '--nowarn:40'.
and "Children = children" in the "parent" definition is highlighted.
What am i doing wrong?
Edit:
One more point: when i move the "Builder" (which worked) into a different assembly (e.g. the test assembly) it immediately stops working with:
error FS0261: Recursive values cannot be directly assigned to the non-mutable field 'Children' of the type 'Parent' within a recursive binding. Consider using a mutable field instead.
Edit:
Based on the comments I tried
let create name kids =
let rec makeChild kid = { kid with Parent = parent |> Some }
and adult = createAdult name 42
and parent =
{ adult with Children = children }
and children = kids |> List.map makeChild
but still no luck - the compiler still does not see this usecase similar to the working one :(
First of all, the message you posted in your question is just a warning - it tells you that you can only initialize a recursive value if the construction does not evaluate the entire value immediately (this cannot be done when the first value depends on the second and vice versa).
You can sometimes just ignore the warning, but in your case, the values are actually mutually dependent, so the following gives an error:
Builder2.create "A" [Builder2.createChild "B"]
System.InvalidOperationException: ValueFactory attempted to access the Value property of this instance.
One way to introduce some form of delay is to change the parent to include children as a lazy sequence seq<'T> rather than a fully evaluated list list<'T>:
type Parent = {
Name : string
Age : int
Children : Child seq }
and Child = {
Name : string
Parent : Parent option }
Then you also need to change Builder2 to use Seq.map (to keep things lazy):
let create name kids =
let rec makeChild kid = { kid with Parent = parent |> Some }
and parent =
{ (createAdult name 42) with
Children = children
}
and children = kids |> Seq.map makeChild
Now you still get the warning (which you can turn off), but the following works and creates a recursive value:
let p = Builder2.create "A" [Builder2.createChild "B"]
As an aside, I think it is probably better to avoid recursive values - I suspect that one way reference (parent referencing children, but not the other way round) would let you do what you need - and your code would likely be simpler.
cartermp found and posted the solution here:
https://github.com/Microsoft/visualfsharp/issues/4201
I published a repro here
https://github.com/plainionist/DevNull/tree/master/src/FSharpCopyRecordRecursive
and of course the proposed solution works like a charm
I have a project that uses arrays of objects that I'm thinking of moving to es6 Sets or Maps.
I need to quickly get a random item from them (obviously trivial for my current arrays). How would I do this?
Maps and Sets are not well suited for random access. They are ordered and their length is known, but they are not indexed for access by an order index. As such, to get the Nth item in a Map or Set, you have to iterate through it to find that item.
The simple way to get a random item from a Set or Map would be to get the entire list of keys/items and then select a random one.
// get random item from a Set
function getRandomItem(set) {
let items = Array.from(set);
return items[Math.floor(Math.random() * items.length)];
}
You could make a version that would work with both a Set and a Map like this:
// returns random key from Set or Map
function getRandomKey(collection) {
let keys = Array.from(collection.keys());
return keys[Math.floor(Math.random() * keys.length)];
}
This is obviously not something that would perform well with a large Set or Map since it has to iterate all the keys and build a temporary array in order to select a random one.
Since both a Map and a Set have a known size, you could also select the random index based purely on the .size property and then you could iterate through the Map or Set until you got to the desired Nth item. For large collections, that might be a bit faster and would avoid creating the temporary array of keys at the expense of a little more code, though on average it would still be proportional to the size/2 of the collection.
// returns random key from Set or Map
function getRandomKey(collection) {
let index = Math.floor(Math.random() * collection.size);
let cntr = 0;
for (let key of collection.keys()) {
if (cntr++ === index) {
return key;
}
}
}
There's a short neat ES6+ version of the answer above:
const getRandomItem = iterable => iterable.get([...iterable.keys()][Math.floor(Math.random() * iterable.size)])
Works for Maps as well as for Sets (where keys() is an alias for value() method)
This is the short answer for Sets:
const getRandomItem = set => [...set][Math.floor(Math.random()*set.size)]
I wonder if this is even possible at all as the question suggest.
My problem is that I cannot seem to grasp how to handle the fact that a given input value can have multiple children. The problem is easily solved by using the mutable SortedSet variable as shown below. But I would really like to find out if this is a problem possible to solve with pure recursion and creation of new un-muted lists or similar. I hope my question is clear. I fear I'm ignorant to the easy conclusion that it's not possible.
As you can see bellow the if(true) will return a list but the else will return a list of list. So the code bellow is not in working state.
let someSet = new System.Collections.Generic.SortedSet<string>()
let rec children(value:string,listSoFar) =
printfn "ID: %A" value
someSet.Add(value) works fine of course.
let newList = List.append listSoFar [value]
if(not (hasChildren(value))) then
newList
else
let tmpCollection = database.GetCollection<Collection>("Collection")
let tmpQuery = Query.EQ("Field",BsonValue.Create(value))
let tmpRes = tmpCollection.Find(tmpQuery)
[ for child in tmpRes do
yield children(child.Value,newList) ]
let resultList = children("aParentStartValue",[])
//Or do i need to use someSet values?
Unless the tree is very deeply nested (in which case, this would be inefficient), you can write the code as a recursive F# sequence expression that generates elements using yield and yield!
let rec children (value:string) = seq {
// Produce the current value as the next element of the sequence
yield value
if hasChildren value then
// If it has children, then get all the children
let tmpCollection = database.GetCollection<Collection>("Collection")
let tmpQuery = Query.EQ("Field",BsonValue.Create(value))
let tmpRes = tmpCollection.Find(tmpQuery)
// For each child, generate all its sub-children recursively
// and return all such elements as part of this sequence using 'yield!'
for child in tmpRes do
yield! children child.Value }
// Using 'List.ofSeq' to fully evaluate the lazy sequence
let resultList = List.ofSeq (children "aParentStartValue")
If the tree is more deeply nested, then the situation is a bit more difficult. When iterating over all the children, you'd need to pass the list collected so far to the first children, get the results and then pass the resulting list to the next children (using something like List.fold). But the above is clean and should work in most cases.
In Lua, I have a tree relationship structure between objects where an object can have multiple children, but only one parent object, i.e.
obj---obj1---obj2---objd3---obj4---obj5---obj6
If I want to know obj6's 'distant' parents instead of just the immediate parent obj5, how can I achieve that? I just need a list of parents two or more levels above the current object, and the API I'm working with only has a obj.parent property.
Pseudo-code would also be helpful to get me in the right direction.
obj.parent -- immediate parent (obj5)
obj.parent.parent -- parent's parent (obj4)
obj.parent.parent.parent -- parent's parent's parent (obj3)
So on and so forth?
If you want to avoid trying to referencing a non-existent parent, I supposed you could do something like:
function getAncestor(obj, depth)
if not obj.parent then
return nil
elseif depth > 1 then
return getAncestor(obj.parent, depth-1)
end
return obj.parent
end
-- get parent
obj = getAncestor(obj6)
-- get great great grandparent
obj = getAncestor(obj6, 3)
Well, if your api supports .parent, can't you do something like the following? I'm rusty with Lua but this should offer a start.
local function GetAncestors(child)
local ancestors = {};
if child.parent then
local i = 0;
ancestors[0] = child.parent;
while ancestors[i].parent do
ancestors[i + 1] = ancestors[i].parent;
i = i + 1;
end
end
return ancestors;
end
I'm looking to get all values associated with a key in a dictionary. Sometimes the key holds a single dictionary, sometimes a list of dictionaries.
a = {
'shelf':{
'book':{'title':'the catcher in the rye', 'author':'j d salinger'}
}
}
b = {
'shelf':[
{'book':{'title':'kafka on the shore', 'author':'haruki murakami'}},
{'book':{'title':'atomised', 'author':'michel houellebecq'}}
]
}
Here's my method to read the titles of every book on the shelf.
def print_books(d):
if(len(d['shelf']) == 1):
print d['shelf']['book']['title']
else:
for book in d['shelf']:
print book['book']['title']
It works, but doesn't look neat or pythonic. The for loop fails on the single value case, hence the if/else.
Can you improve on this?
Given your code will break if you have a list with a single item (and this is how I think it should be), if you really can't change your data structure this is a bit more robust and logic:
def print_books(d):
if isinstance(d['shelf'], dict):
print d['shelf']['book']['title']
else:
for book in d['shelf']:
print book['book']['title']
Why not always make 'shelf' map to a list of elements, but in the single element case it's a ... single element list? Then you'd always be able to treat each bookshelf the same.
def print_books(d):
container = d['shelf']
books = container if isinstance(container, list) else [container['book']]
books = [ e['book'] for e in books ]
for book in books:
print book['title']
I would first get the input consistent, then loop through all the books even if only one.
def print_books(d):
books = d['shelf'] if type(d['shelf']) is list else [ d['shelf'] ]
for book in books:
print book['book']['title']
I think this looks a little neater and pythonic, although some might argue not as efficient as your original code to create an array with one element and loop through it.