Implementing python slice notation

前端 未结 6 563
轻奢々
轻奢々 2021-02-07 05:06

I\'m trying to reimplement python slice notation in another language (php) and looking for a snippet (in any language or pseudocode) that would mimic the python logic. That is,

相关标签:
6条回答
  • 2021-02-07 05:42

    This is what I came up with (python)

    def mySlice(L, start=None, stop=None, step=None):
        answer = []
        if not start:
            start = 0
        if start < 0:
            start += len(L)
    
        if not stop:
            stop = len(L)
        if stop < 0:
            stop += len(L)
    
        if not step:
            step = 1
    
        if stop == start or (stop<=start and step>0) or (stop>=start and step<0):
            return []
    
        i = start
        while i != stop:
            try:
                answer.append(L[i])
                i += step
            except:
                break
        return answer
    

    Seems to work - let me know what you think

    Hope it helps

    0 讨论(0)
  • 2021-02-07 05:42

    I can't say there's no bug in the codes, but it had past your test program :)

    def mySlice(L, start=None, stop=None, step=None):
        ret = []
        le = len(L)
        if step is None: step = 1
    
        if step > 0: #this situation might be easier
            if start is None: 
                start = 0
            else:
                if start < 0: start += le
                if start < 0: start = 0
                if start > le: start = le
    
            if stop is None: 
                stop = le
            else:
                if stop < 0: stop += le
                if stop < 0: stop = 0
                if stop > le: stop = le
        else:
            if start is None:
                start = le-1
            else:
                if start < 0: start += le
                if start < 0: start = -1
                if start >= le: start = le-1
    
            if stop is None: 
                stop = -1 #stop is not 0 because we need L[0]
            else:
                if stop < 0: stop += le
                if stop < 0: stop = -1
                if stop >= le: stop = le
    
        #(stop-start)*step>0 to make sure 2 things: 
        #1: step != 0
        #2: iteration will end
        while start != stop and (stop-start)*step > 0 and start >=0 and start < le:
            ret.append( L[start] )
            start += step
    
        return ret
    
    0 讨论(0)
  • 2021-02-07 05:58

    This is based on @ecatmur's Python code ported again to PHP.

    <?php
    function adjust_endpoint($length, $endpoint, $step) {
        if ($endpoint < 0) {
            $endpoint += $length;
            if ($endpoint < 0) {
                $endpoint = $step < 0 ? -1 : 0;
            }
        }
        elseif ($endpoint >= $length) {
            $endpoint = $step < 0 ? $length - 1 : $length;
        }
        return $endpoint;
    }
    
    function mySlice($L, $start = null, $stop = null, $step = null) {
        $sliced = array();
        $length = count($L);
    
        // adjust_slice()
        if ($step === null) {
            $step = 1;
        }
        elseif ($step == 0) {
            throw new Exception('step cannot be 0');
        }
    
        if ($start === null) {
            $start = $step < 0 ? $length - 1 : 0;
        }
        else {
            $start = adjust_endpoint($length, $start, $step);
        }
    
        if ($stop === null) {
            $stop = $step < 0 ? -1 : $length;
        }
        else {
            $stop = adjust_endpoint($length, $stop, $step);
        }
    
        // slice_indices()
        $i = $start;
        $result = array();
        while ($step < 0 ? ($i > $stop) : ($i < $stop)) {
            $sliced []= $L[$i];
            $i += $step;
        }
        return $sliced;
    }
    
    0 讨论(0)
  • 2021-02-07 06:01

    This is a solution I came up with in C# .NET, maybe not the prettiest, but it works.

    private object[] Slice(object[] list, int start = 0, int stop = 0, int step = 0)
    {
        List<object> result = new List<object>();
    
        if (step == 0) step = 1;
        if (start < 0)
        {
            for (int i = list.Length + start; i < list.Length - (list.Length + start); i++)
            {
                result.Add(list[i]);
            }
        }
        if (start >= 0 && stop == 0) stop = list.Length - (start >= 0 ? start : 0);
        else if (start >= 0 && stop < 0) stop = list.Length + stop;
    
        int loopStart = (start < 0 ? 0 : start);
        int loopEnd = (start > 0 ? start + stop : stop);
    
        if (step > 0)
        {
            for (int i = loopStart; i < loopEnd; i += step)
                result.Add(list[i]);
        }
        else if (step < 0)
        {
            for (int i = loopEnd - 1; i >= loopStart; i += step)
                result.Add(list[i]);
        }
    
        return result.ToArray();
    }
    
    0 讨论(0)
  • 2021-02-07 06:04

    Here's a straight port of the C code:

    def adjust_endpoint(length, endpoint, step):
         if endpoint < 0:
             endpoint += length
             if endpoint < 0:
                 endpoint = -1 if step < 0 else 0
         elif endpoint >= length:
             endpoint = length - 1 if step < 0 else length
         return endpoint
    
    def adjust_slice(length, start, stop, step):
         if step is None:
             step = 1
         elif step == 0:
             raise ValueError("step cannot be 0")
    
         if start is None:
             start = length - 1 if step < 0 else 0
         else:
             start = adjust_endpoint(length, start, step)
    
         if stop is None:
             stop = -1 if step < 0 else length
         else:
             stop = adjust_endpoint(length, stop, step)
    
         return start, stop, step
    
    def slice_indices(length, start, stop, step):
         start, stop, step = adjust_slice(length, start, stop, step)
         i = start
         while (i > stop) if step < 0 else (i < stop):
             yield i
             i += step
    
    def mySlice(L, start=None, stop=None, step=None):
         return [L[i] for i in slice_indices(len(L), start, stop, step)]
    
    0 讨论(0)
  • 2021-02-07 06:05

    I've written a PHP port based on the C code, optimized for step sizes -1 and 1:

    function get_indices($length, $step, &$start, &$end, &$size)
    {
            if (is_null($start)) {
                    $start = $step < 0 ? $length - 1 : 0;
            } else {
                    if ($start < 0) {
                            $start += $length;
                            if ($start < 0) {
                                    $start = $step < 0 ? -1 : 0;
                            }
                    } elseif ($start >= $length) {
                            $start = $step < 0 ? $length - 1 : $length;
                    }
            }
    
            if (is_null($end)) {
                    $end = $step < 0 ? -1 : $length;
            } else {
                    if ($end < 0) {
                            $end += $length;
                            if ($end < 0) {
                                    $end = $step < 0 ? - 1 : 0;
                            }
                    } elseif ($end >= $length) {
                            $end = $step < 0 ? $length - 1 : $length;
                    }
            }
    
            if (($step < 0 && $end >= $start) || ($step > 0 && $start >= $end)) {
                    $size = 0;
            } elseif ($step < 0) {
                    $size = ($end - $start + 1) / $step + 1;
            } else {
                    $size = ($end - $start - 1) / $step + 1;
            }
    }
    
    function mySlice($L, $start = NULL, $end = NULL, $step = 1)
    {
            if (!$step) {
                    return false; // could throw exception too
            }
            $length = count($L);
            get_indices($length, $step, $start, $end, $size);
    
            // optimize default step
            if ($step == 1) {
                    // apply native array_slice()
                    return array_slice($L, $start, $size);
            } elseif ($step == -1) {
                    // negative step needs an array reversal first
                    // with range translation
                    return array_slice(array_reverse($L), $length - $start - 1, $size);
            } else {
                    // standard fallback
                    $r = array();
                    for ($i = $start; $step < 0 ? $i > $end : $i < $end; $i += $step) {
                            $r[] = $L[$i];
                    }
                    return $r;
            }
    }
    
    0 讨论(0)
提交回复
热议问题