javascriptpythonjsonjuliacode-translation

Why does passing a large dictionary from python to julia flatten contained multidimensional lists?


Okay so...I'm in the process of creating a python client for a coding game I play. This game is originally created in javascript and employs a json object of game data found at https://adventure.land/data.js. Within this data, each map has a list of doors, and each door within this list is a list of attributes. For example:

"doors":[[-965,-176,24,30,"woffice",0,1],[536,1665,64,32,"tunnel",0,2],[168,-149,32,40,"bank",0,3],[160,1370,24,32,"cave",0,4],[232,384,24,30,"arena",0,6],[-472,131,24,30,"tavern",0,8],[616,610,32,40,"mansion",0,10],[1936,-23,24,24,"level1",1,11],[169,-404,24,40,"hut",0,14],[1600,-547,60,40,"halloween",4,15],[312,-335,32,32,"mtunnel",0,16],[967,-584,32,32,"mtunnel",1,17],[1472,-434,32,32,"mtunnel",2,18]]

However, when sent from python to julia, it suddenly becomes:

"doors":[-965,-176,24,30,"woffice",0,1,536,1665,64,32,"tunnel",0,2,168,-149,32,40,"bank",0,3,160,1370,24,32,"cave",0,4,232,384,24,30,"arena",0,6,-472,131,24,30,"tavern",0,8,616,610,32,40,"mansion",0,10,1936,-23,24,24,"level1",1,11,169,-404,24,40,"hut",0,14,1600,-547,60,40,"halloween",4,15,312,-335,32,32,"mtunnel",0,16,967,-584,32,32,"mtunnel",1,17,1472,-434,32,32,"mtunnel",2,18]

Is there some way to prevent this from happening? If not, is there a possible workaround? Because my for door in doors code in python won't exactly have the same effect when given a direct translation to julia considering the random list flattening.

Edit: I've been asked to provide "minimum reproducible code" but I'm not too sure what the minimum is so I'll just say...

  1. create a some function in julia that prints a dictionary
function printDict(d)
    println(d)
end
  1. create a dictionary in python that contains a nested list
nestedlistdict = {"data": [[0,1,2,3],[4,5,6,7]]}
  1. call the printDict function from python while sending the nestedlistdict variable as an argument
from julia import Main
Main.include("path/to/your/julia/file")
Main.file.printDict(nestedlistdict)
  1. result should be: Dict{Any, Any}("data" => [[0, 1, 2, 3], [4, 5, 6, 7]])but instead my result is Dict{Any, Any}("data" => [0 1 2 3; 4 5 6 7])

Edit2: upon further testing, it seems to be having the issue because it converts a nested list into a Matrix object instead of a nested Vector object.


Solution

  • Julia uses the same interpretation of list of lists as numpy:

    >>> np.array([[1,2,3],[4,5,6]])
    array([[1, 2, 3],
           [4, 5, 6]])
    

    or in Julia:

    julia> using PyCall
    
    julia> py"[[1,2,3],[4,5,6]]"
    2×3 Matrix{Int64}:
     1  2  3
     4  5  6
    

    If you want to have an actual vector of vectors you need to do the same way as you need to do a vector of numpy arrays. Python version:

    >>> [np.array([1,2,3]),np.array([1,2,3])]
    [np.array([1, 2, 3]), np.array([1, 2, 3])]
    

    Julia version (this is what you are actually asking for):

    julia> np = pyimport("numpy");
    
    julia> py"[$np.array([1, 2, 3]), $np.array([1, 2, 3])]"
    2-element Vector{Vector{Int32}}:
     [1, 2, 3]
     [1, 2, 3]
    

    Another, perhaps simpler option could be packing that all to a tuple:

    julia> py"tuple([[1,2,3],[4,5,6]])"
    ([1, 2, 3], [4, 5, 6])