Can I use rtrim() here?

I have

$x = '1/3/5';
//the string

Is there a way to convert it to

$x  = '1';
//the number

I was thinking like

$x = rtrim($x,'/');
$x = (int)$x;

What do you get if you try that?

What are the exact requirements for the trimming?
Will $x always equal '1/3/5'?
Might it sometimes equal '25/9/84' or '0002/3654/0125' or '5/6/8/9/2/3' or 'a/12/b0/9'?

Are we talking first single character string?
The first (any length) string before the first slash?
There are a few potential possibilities.

2 Likes

ok, so x can be

$x = "1/3/5";
//or
$x  = "2/4/6";
//or
$x = "4/6";
//or
$x = "3";
//or
$x = "2";

So, it is always a string, but its always at least 1 number. if its ever more than 1 number, they will be separated by a /. Id like to get the first number on the left side, and make it an nteger

1 Like

If it is “always a string” then there are numerous functions which could solve your problem - Search “PHP functions strings”:

https://www.php.net/manual/en/ref.strings.php

1 Like

I would do substr($x, 0, strpos('/', $x) + 1);

i.e. everything from the start of the string up until the first /

3 Likes

Lots of ‘ifs’ possible here.

IF it will always be numbers and slashes, (int) $x will do the job by itself, because the parser truncates everything after a non-int-able character.

1 Like

It works, but it feels like using a chainsaw to peel an orange …

shrug his desired output is the integer value of the first number in the string.

You did it with substringing the string, i did it by turning the string into the desired output type. Both operations chopped off the end of the string. Both operations assume that the string is made of numbers followed by optionally slashes and more numbers. And at the end he’d have to (int) the result regardless. So… trade my chainsaw for your axe?

1 Like

Incidentally, substringing… doesnt work if the string is “12”, because strpos will kick back false, `false + 1 is 1, and substr(“12”,0,1) is “1”, not “12”.

So… as long as the numbers are less than 10, we’re good. (This is why we keep asking for a concrete definition of your input, @lurtnowski!)

1 Like

then again… if we’re guaranteeing the number is less than 10, and will occur first in the string…
$x[0]?

(Welcome to the rambling diatribe against my own thoughts that occurs inside my head while solving a coding challenge.)

I would just explode() on the ‘/’ character (which is probably the complement of how the value was originally generated), trim() the resulting elements (see array_map() and trim()), cast to an integer if needed (see array_map() again, and intval()), then test/reference the resulting element(s).

$x = "1/3/5";

$x = array_map('intval',array_map('trim',explode('/',$x)))[0];

var_dump($x);

Note: explode() works as expected for zero or more occurrences of the delimiter and any number of characters in a value.

My point was mostly that the solution that uses (sub)strings is known and documented and using tools that are meant for strings. But using string to int casting you’re potentially opening yourself up to weird PHP behaviours. Now here it’s probably fine, but in general I tend to keep things in the datatype that I got them in, until I’m certain that what I’ve massaged it to is convertable to the target datatype, before actually casting it. For example, what if PHP decided that mathematical operators in strings must be parsed to, all of a sudden 1/2 would be 0.5 rather than 1. Unlikely, but casting is far less strict defined than functions (at least in my opinion).

I would certainly check against that beforehand. This would be my production version:

function getFirstPart(string $x) {
  $pos = strpos('/', $x);
  if (false === $pos) {
     throw new InvalidArgumentException('getFirstPart expects argument in format X/Y/Z');
  }

  $part = substr($x, 0, $pos + 1);

  if (!ctype_digit($part)) {
    throw new InvalidArgumentException(sprintf('First part of "%s" passed to getFirstPart was expected to be number, got "%s"', $x, $part);
  }

  return (int) $part;
}

Overkill? Maybe, depends on the usecase. In cases where a borked string without any numbers would result in the price of something being sold would be zero then I would take the above over casting any day of the week.

The main advantage of this approach, even though it might seem a bit much, is that I can be sure that whatever comes out is something that’s useful. It’s not based on assumptions that the input will always adhere to some pattern and will stop with useful messages whenever it’s not, rather than moving forward fist first with data that’s incorrect causing who knows what kind of havoc in the system.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.