ID:891677
 
I was just experimenting a bit and wanted to see if there was a good way to get the size of a multidimensional list. This is what I came up with: Code:
proc
get_ListDimensions(var/list/current)
if(!islist(current)) CRASH("Not a valid list")
var/list/dimensions = new()
while(islist(current))
dimensions += length(current)
current = current[1]
return dimensions
The problem is, this doesn't take into account lists of lists. It only checks the first element of a each nested list which is fine if I know what I am sending it however if it was tried on a list that did not have a consistent size. (lets say a list that contained a bunch of different types of lists). It would ignore that and report the wrong info. Does anyone have a method to verify that a multidimensional list is actually a consistent multidimensional list? It would have to check every element in every nested list.
If you need to ensure it's a true multidimensional list and not a jagged list (list of lists of varying sizes), you could always wrap it in a datum. You'll lose the ability to use operators on it, however. If it's 3-dimensions or more, it might be worth the access tradeoff for the performance (compared to recursively looping through it).

I have to ask, though, in what context are you working that you can't always control if the list will be a true multidimensional list or not?
Actually, I was working on a making a datum to hold a multidimensional list in a single list (because I keep reading that BYOND is bad at multidimensional lists).

This proc was going to be used to help convert a traditional multidimensional list to the new matrix datum. If the list is a jagged list it can't be converted and I would need break out of it.

Edit: For clarity this is the islist() proc
proc/islist(list/l)
return istype(l)
It seems I may have found a solution although it is a bit recursion happy:

proc
recurMatrixCheck(var/list/L)
if(!islist(L)) return null
var/list/c_list = new
var/list/t_list = new
for(var/i in L)
if(!islist(i)) return list(L.len)
c_list = recurMatrixCheck(i)
if(!t_list.len) t_list = c_list
else if(!recurCompareList(t_list,c_list)) return list(L.len)
t_list = c_list
c_list.Insert(1,L.len)
return c_list

recurCompareList(var/list/L1,var/list/L2)
if(L1.len!=L2.len) return 0
for(var/i=L1.len,i>0,i--)
if(islist(L1[i])||islist(L2[i]))
if(!recurCompareList(L1[i],L2[i])) return 0
else if(L1[i]!=L2[i]) return 0
return 1


Here is a test:
client
verb
Test_M()
var/list/m = new(5,5,4,6,4,2,54)
world << list2text(recurMatrixCheck(m))
m = list(list(list(4,5,3,2),2,3,4,5),list(5,4,3,2,1),list(1,2,3,4,5),list(2,4,5,3,2))
world << list2text(recurMatrixCheck(m))
m = list(list(1,2,3,4,5),list(3,4,5),list(1,2,3,4,5),list(2,4,5,3,2,4,5))
world << list2text(recurMatrixCheck(m))

proc //Just for testing purposes
list2text(var/list/l)
.=""
for(var/i in l) .+="[i] "
return .


I am not sure I am happy with all the recursion and all the variables I am creating to test this. Anyone else have any ideas?

                       Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
---------------------- --------- --------- --------- ---------
/proc/recurMatrixCheck 0.087 0.734 0.736 7940
/client/verb/Test_M 0.021 0.142 0.142 1
/proc/recurCompareList 0.023 0.028 0.029 4803
/proc/islist 0.011 0.016 0.020 36540
/proc/list2text 0.000 0.000 0.000 3