1

I have to translate two Python functions into PHP. The first one is:

def listspaces(string):
        return [i -1 for i in range(len(string)) if string.startswith(' ', i-1)]

I am assuming that this will check for space in provided string and return True when first occurrence of space is found, is this correct ?

What is i-1 here ? is it -1 ?

In PHP we use [] for arrays . Here we are [] with return, will this function return true or false or array of locations of spaces ?

Second function is

def trimcopy(copy, spaces, length=350):

    try:
        if len(copy) < length:
            return copy
        else:
            loc = 0
            for space in spaces:
                if space < length:
                    loc = space
                else:
                    return copy[:loc]
    except :
        return None

Whats for space in spaces: here and whats is this return copy[:loc]

4
  • check python list comprehension, for loops and python slicing.... Commented Sep 26, 2012 at 11:03
  • 1
    these are quite bizarre functions (trimcopy especially)! Commented Sep 26, 2012 at 11:15
  • I comeup with this as php alternate for both functions list($short) = explode("\n",wordwrap($string,100)); is this correct ? Commented Sep 26, 2012 at 12:18
  • That doesn't quite do it, try this bit inside the else block in trimcopy: list($newtext) = explode(" ",wordwrap($string,350," "));, however it is difficult to tell what the function intends (as it's surely buggy)! Commented Sep 26, 2012 at 14:15

5 Answers 5

2

I think a good process for these type of conversions is:

  • work out what the code is doing

  • refactor it into a PHP-style in Python (this enables you to check that the logic still works, e.g. using assertion tests). e.g. convert list comprehensions to for loops

  • convert to PHP

For example, listspaces(string) returns the positions of spaces in string, and although using a list comprehension is Pythonic, it's not very "PHP-onic".

def listspaces2(string): #PHP-onic listspaces
    space_positions = []
    for i in range(len(string))]:
        if string[i] == ' ':
            space_positions.append(i)
    return space_positions

The second example, trimcopy is rather trickier (since the try, except may purposefully be catching some expected - to the writer (!) - exceptions - two possibles are string not having a len and spaces containing values longer than len(copy)), but it's hard to say so it's a good idea to refactor in Python and test.

You can do array slicing in PHP like copy[:loc] using array_slice($copy, 0, $loc);.

Note: usually in Python we would state explicitly which exception we are defending against (as opposed to Pokemon exception handling).

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

5 Comments

To the try … except: I guess this is because it is not checked anywhere if copy really consists of at least loc chars in copy[:loc].+
@feeela I guess that too... but it could be hiding some sinister bug in the rest of the code!
I comeup with this as php alternate for both functions list($short) = explode("\n",wordwrap($string,100)); is this correct ?
Nearly, this does only the bit inside the else block in trimcopy: list($newtext) = explode(" ",wordwrap($string,350," ",true));, although it is difficult to tell what the function intends (as it's surely buggy)!
@hayden, Thanks I will add this line if (strlen($string) > 350) { list($newtext) = explode(" ",wordwrap($string,350," ",true)); }
1

You may notice that the first function could also have been written as

def listspaces(str):
    return [i for i, c in enumerate(str) if c==' ']

That version has the following straightforward conversion to PHP:

function listspaces($str) {
    $spaces = array();

    foreach (str_split($str) as $i => $chr)
        if ($chr == ' ') $spaces[] = $i;

    return $spaces;
}

As for the other function, this seems to do the same thing in very nearly the same idiom:

function trimcopy($copy, $spaces, $length=350) {
    if (strlen($copy) < $length) {
        return $copy;
    } else {
        foreach ($spaces as $space) {
            if ($space < $length) {
                $loc = $space;
            } else {
                return substr($copy, 0, $loc);
            }
        }
    }
}

As others have pointed out, the intent of both of these functions could probably be better expressed by using wordwrap.

2 Comments

Thanks, do u agree with this line as alternate for these two functions list($short) = explode("\n",wordwrap($string,350));
If they are only ever used in combination, they seem designed to do just that. For that matter, you could have used textwrap.wrap in python's standard library.
1

Why don't you just test those functions to see what they are doing?

listspaces(string) returns an array with the positions of all spaces within the string:

$ ipython
IPython 0.10.2 -- An enhanced Interactive Python.

In [1]: def listspaces(string):
   ...:     return [i -1 for i in range(len(string)) if string.startswith(' ', i-1)]
   ...:

In [2]: listspaces('Hallo du schöne neue Welt!')
Out[2]: [5, 8, 16, 21]

(i -1 is the position of a space when starting to count with zero)

I don't know much about Python and I can't paste the second function as there are to many "IndentationError"'s.

I think that trimcopy() will return a string (from input copy), where everything behind the last space position given in the array spaces (obviously a return value from listspaces()) is trimmed, unless the input is no longer than length. In other words: the input is cut off at the highest space position that is smaller than length.

As of the example above, the part ' Welt!' will get cut off:

s = 'Hallo du schöne neue Welt!'
trimcopy( s, listspaces( s ) )
/* should return: 'Hallo du schöne neue' */

5 Comments

I tried it , first one is returning array of locations and second is not doing anything its returning same text but trimmed version
If copy is longer than length, it returns the chunk of copy before the first space, this may or may not be longer than length, this behaviour can't be good...
@hayden well, I didn't wrote those functions…
@feeela I know! But it is amusing to compare output from 'a '*100, 'a '*200 and 'a'*400. :)
I comeup with this as php alternate for both functions list($short) = explode("\n",wordwrap($string,100)); is this correct ?
0

The first function returns indexes of all spaces in given string.

  • range(len(string)) results in list with numbers from 0 to length of the input string
  • if string.startswith(' ', i-1)] condition is evaluated for each index i, it returns true when string (here it is not a keyword) starts with ' ' at position given by the index i-1

The result is as feela posted.

For the second function I don't know what the spaces parameter is.

Hope this will help you to create a PHP version.

Comments

0

This is equivalent to both the functions in Python

list($short) = explode("\n",wordwrap($string,350));

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.