0

I need to split this string to an array:

$string = "9583526578','9583636523','9673522574','9183556528','9983023378";

Here's how I want my array to look like after splitting:

@foo = [
           [9583526578, 9583636523],
           [9673522574, 9183556528],
           [9983023378]
       ]

As you might have noticed, I need to split this string into groups of n (2 in this example) but still consider remainder if it doesn't match with n.

How can this be done in Perl?

I've done my research and experimentations but can't seem to get it right after a couple of hours.

Thanks for your time! :)

3
  • 2
    Did you mean to add single quotes before the first number and after the last? Commented Jun 2, 2011 at 2:28
  • 1
    No. The string really looks like that. :) Commented Jun 2, 2011 at 2:59
  • Thanks for everyone's ideas. It helped me explore other possibilities of solving this. :) Commented Jun 2, 2011 at 9:07

5 Answers 5

4

If you can trust they're all integers, extraction is easy. Just grab all the integers.

my @numbers = $string =~ /(\d+)/g;

Then splitting them into pieces of two...

push @matrix, [splice @numbers, 0, 2] while @numbers;

Not as memory efficient as doing it in place, but simple code (if you grok list processing).

If the only reason you're splitting them into pairs is to process them in pairs, you can destructively iterate through the array...

while( my @pair = splice @numbers, 0, 2 ) {
    ...
}

Or you can iterate in pairs in one of the rare valid uses of a 3-part for loop in Perl.

for(
    my $idx = 0;
    my @pair = @numbers[$idx, $idx+1];
    $idx += 2;
)
{
    ...
}

Finally, you can get fancy and use perl5i.

use perl5i::2;
@numbers->foreach( func($first, $second) { ... } );

You can also use List::MoreUtils natatime.

Sign up to request clarification or add additional context in comments.

1 Comment

Wow never knew about these approaches. Anyhow I'll be trying them out and see which ones I find more applicable in my problem. It just seems logical to mark this as my accepted answer. Thanks! :)
0

First split on "','" to give you an array, then group the elements as desired.

Comments

0

I would recommend using regex to retrieve the numbers using '([0-9]+)' and just manually building @foo. Or as @MRAB suggested, split is even more straight-forward. Any reason you are aiming at Regex for this?

2 Comments

I've tried out @MRAB's approach a while back. However, I just thought that doing this via regex would be more efficient since I would be avoiding looping over the array and then grouping them manually (Normally I would have a string like that with more than a thousand number groups). This thought, of course, is based from my limited knowledge. I'm open for suggestions.
Of course I'd still have to loop over the array in my desired output but it would be lesser iterations since it's already pre-grouped.
0

Tons of different ways. Here's one:

$foo[0] = [];  # assuming you really meant an array of arrays of arrays as you showed
while ($string =~ m/([0-9]++)[^0-9]*+([0-9]++)?/g) {
    push @{ $foo[0] }, [ $1, $2 // () ];
}

(Did you really mean an array containing just one reference to an array of arrayrefs?)

Comments

0

This should be a reasonably close fit to your desired behavior:

my @foo;
push @foo, [ $1, $2 // () ] while $string =~ / (\d+) (?: \D+ (\d+) ) ? /gx;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.