Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411722 Posts in 69402 Topics- by 58450 Members - Latest Member: FezzikTheGiant

May 22, 2024, 04:12:54 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Creating nested arrays from a String
Pages: [1]
Print
Author Topic: Creating nested arrays from a String  (Read 2243 times)
st33d
Guest
« on: June 07, 2010, 01:20:31 AM »

I think I can eventually get my head around this problem, but I'm currently stuck and I'm wondering what suggestions other people have.

(Any mention of compression and I will strap you to a rocket and fire it into the sun.)

Here's the problem:

I have a data stored like so:

"2,3,4,(1,2,3,4,(1,2),2),3,(4,5,6),((12,3,23),2,1),4"

So I want to convert that into an array. Each section in parenthesis implies a nested array.

What would that array be structured like? Well in as3 it would be like so:

myArray:Array = [2, 3, 4, [1, 2, 3, 4, [1, 2], 2], 3, [4, 5, 6], [[12, 3, 23], 2, 1], 4];

My first guess was to split the string at the commas and then try to start pushing and poping a stack whenever I hit any brackets.

(Actually my first guess was to use regex, but I know what you're going to reply to that.)

And my brain has kind of melted at the point where I'm trying to visualise how this pushing and popping business works in code. Any pointers?
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #1 on: June 07, 2010, 02:53:04 AM »

Assuming you've got just numbers, and a fixed dimension of array, I'd say regexes are ok for this.

Otherwise, got for a tokenizer/scanner combination like every other parser in the world;

// Regex for tokenizing is more acceptable, but this can also be done manually:
var tokenize = input.split(/\b/g);
var arrayStack = [[]];
for each(var token in array)
{
  switch(token)
  {
    case ",": break; // Ignore
    case "(": arrayStack.push([]); break;
    case ")":
      var current = arrayStack.pop();
      arrayStack.last.push(current);
      break;
    default:
      arrayStack.last.push(parseInt(token));
      break;
  }
}
assert(arrayStack.length==1,"Unbalanced array");
return arrayStack[0];


So yeah, pretty much what you thought. Note that you *can* do tokenizing and parsing in the same scan, but this is not advised.
Logged
Mikademus
Level 10
*****


The Magical Owl


View Profile
« Reply #2 on: June 07, 2010, 03:17:50 AM »

The best solution to this is to reshuffle the items through a pseudo-random seed until you have a linear array without nesting. Then it can be compressed to less than 69 bits.

I'll go look for a rocket now...
Logged

\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
Pineapple
Level 10
*****

~♪


View Profile WWW
« Reply #3 on: June 07, 2010, 03:22:33 AM »

 Big Laff
Logged
grapefrukt
Level 1
*



View Profile WWW
« Reply #4 on: June 07, 2010, 04:33:27 AM »

i was bored: http://wonderfl.net/c/7B1c
Logged
st33d
Guest
« Reply #5 on: June 07, 2010, 05:15:22 AM »

Nice!  Kiss

I'd gotten halfway into the problem and then fucked it up. I'll have a proper look when I get home.
Logged
David Pittman
Level 2
**


MAEK GAEM


View Profile WWW
« Reply #6 on: June 07, 2010, 12:45:10 PM »

I'd make it a recursive function that takes as input an array and the current index in the string. When the parser hits an opening parenthesis, it allocates an inner array and recurses. Though maybe the string index would have to be global so it would persist as the recursion unwinds. That would defeat the elegance of doing it recursively. Maybe the return value of the function could be the modified string index? That would probably work. Also, this becomes a harder problem if you don't have dynamic arrays because you have to allocate up front for an array whose size isn't known yet. Maybe do two passes in that case: one to count and one to build the arrays.
Logged

st33d
Guest
« Reply #7 on: June 07, 2010, 01:37:48 PM »

I think grapefrukt's number does the job nicely.  Beer!

Recursion is a dodgy thing in Flash. I had to implement a flood fill using a couple of functions once because it got past 15 levels so easily. In this case it won't happen.

My task was to create a format for generating parameters for monsters and items. I could indeed just generate all the objects prior to the level loading on the fly, but I wanted something I could possibly output to xml without having to come up with loads of different separators. And I like breaking objects down to idents when I not using them to save memory.
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #8 on: June 07, 2010, 02:12:41 PM »

Gad, why not just use XML, then? It's pretty good for recursive datatypes, and very easy to use in AS3.
Logged
Draknek
Level 6
*


"Alan Hazelden" for short


View Profile WWW
« Reply #9 on: June 07, 2010, 02:15:50 PM »

I would probably be tempted to convert it to JSON (i.e. wrap the whole string in [] and replace () with []) and find an AS3 JSON library, mostly because that would be a useful thing to have lying around in general.
Logged

st33d
Guest
« Reply #10 on: June 07, 2010, 02:55:21 PM »

Gad, why not just use XML, then? It's pretty good for recursive datatypes, and very easy to use in AS3.

Because I have a mutidimensional array describing the layers of the map and I wasn't keen on having floating chunks of xml in what was mostly loads of just zeros and ones describing if a wall was there or not.

Makes for easier reading when I trace out an entire layer of ids.

But having an external list of monsters and items referenced by id in the map may be an idea. I'll sleep on it.
Logged
iopred
Level 0
**


Gutsch


View Profile
« Reply #11 on: June 07, 2010, 10:46:01 PM »

If you absolutely must have it as a string, and you can decide how its encoded try this:

Code:
for(var y:int = 0; y < array.length; y++) {
array[y] = array[y].join("|");
}

var string:String = array.join("#");

Now string should be: 1#3#4#5#3|34#23#2#9#2|3,5,5|5#12

Reverse it with:

Code:
var array:Array = string.split("#");

for(var y:int = 0; y < array.length; y++) {
array[y] = array[y].split("|");
for(var x:int = 0; x < array[y].length; x++) {
array[y][x] = array[x].split(",");
}
}
Logged
st33d
Guest
« Reply #12 on: June 08, 2010, 12:46:35 AM »

Yeah, but there's three levels of splitting, possibly four.

That would require even more separators. I just wanted to go from the outset knowing I could endlessly nest stuff without exausting all the silly characters on my keyboard. This is useful also from a scripting point of view.

I'll probably move over to an xml format in the end anyway. A list of external assets for the level would be easier to edit and load back in.
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic