[Tutor] reference instead of copy

Tim Johnson tim at johnsons-web.com
Sat Oct 18 12:37:28 EDT 2003


* Danny Yoo <dyoo at hkn.eecs.berkeley.edu> [031018 00:10]:

Mornin' Danny: 

As usual, you are chock full of good info. Coming from a "C"
background 'way' back, I would be able to copy a subset of an array
of pointers, work on the data that they referenced and have it reflected
in the original. Haha! But we're not supposed to talk about pointers
here. Rebol's own 'extract' has the same behavior.

Can you point me to some docs or discussions on the
more advanced use of slicing and indexing, if you can think of any?
Thanks!

(and as soon as I'm done with my coffee, I'm going to start thinking
 of 'range' as generating object with the indices I want) 
 there's a solution there, I can just start to see it)

cheers
tim
> 
> On Fri, 17 Oct 2003, Tim Johnson wrote:
> 
> > I have been using the following function (produced by help from this
> > list (thanks!)) which returns a subset of a list.:
> 
> > def extract (oldlist, spacing,ndx=-1):
> > 	if ndx > -1:
> > 		return [oldlist[i][ndx] for i in range (len(oldlist)) if not i%spacing]
> > 	else:
> > 		return [oldlist[i] for i in range (len(oldlist)) if not i%spacing]
> 
> 
> Hi Tim,
> 
> 
> Do you mind if we take a quick sidetrip?  The complexity of the list
> comprehension is slightly high --- let me see what this looks like with
> explicit loops:
> 
> ###
> def extract (oldlist, spacing,ndx=-1):
>     if ndx > -1:
>         results = []
>         for i in range(len(oldlist)):
>             if not i % spacing:
>                 results.append(oldlist[i][ndx])
>     else:
>         results = []
>         for i in range(len(oldlist)):
>             if not i % spacing:
>                 results.append(oldlist[i])
>     return results
> ###
> 
> 
> 
> Hmm... There's some common stuff here.  Let me rework it a little more.
> 
> ###
> def extract (oldlist, spacing,ndx=-1):
>     results = []
>     for i in range(len(oldlist)):
>         if i % spacing == 0:
>             if ndx > -1:
>                 results.append(oldlist[i][ndx])
>             else:
>                 results.append(oldlist[i])
>     return results
> ###
> 
> 
> Does extract() really have to deal with grabbing specific subindices using
> that 'ndx' value?  That's something that I think can be done outside of
> extract().  If it's ok, we can yank it out violently:
> 
> ###
> def extract (oldlist, spacing):
>     results = []
>     for i in range(len(oldlist)):
>         if i % spacing == 0:
>             results.append(oldlist[i])
>     return results
> ###
> 
> 
> Oh!  There's one more simplification we can make if we know a little more
> about the range function() --- range can actually take in a "skip" third
> argument.  For example:
> 
> ###
> >>> range(0, 10, 3)
> [0, 3, 6, 9]
> ###
> 
> 
> If we take advantage of this feature, then that lets us cut out the
> remainder check:
> 
> ###
> def extract (oldlist, spacing):
>     results = []
>     for i in range(0, len(oldlist), spacing):
>         results.append(oldlist[i])
>     return results
> ###
> 
> 
> We can transform this back to its list-comprehension equivalent:
> 
> ###
> def extract(oldlist, spacing):
>     return [oldlist[i] for i in range(0, len(oldlist), spacing)]
> ###
> 
> 
> > # But let's suppose I wish to operate on this subset and have it
> > # reflected in the original list. I can't do this with the above
> > # configuration.
> 
> 
> Very true.  The reason for this is because of the use of the list
> comprehension: list comprehnsions generate fresh new lists.  For example:
> 
> ###
> >>> def makeListCopy(L):
> ...     return [x for x in L]
> ...
> >>> pi = [3, 1, 3, 1, 5, 9, 2, 6]
> >>> pi_copy = makeListCopy(pi)
> >>> pi
> [3, 1, 3, 1, 5, 9, 2, 6]
> >>> pi_copy
> [3, 1, 3, 1, 5, 9, 2, 6]
> ###
> 
> 
> Although they look the same now, they're only clones at birth.
> 
> ###
> >>> del pi[2:]
> >>> pi_copy[2] = 4
> >>>
> >>> pi
> [3, 1]
> >>>
> >>> pi_copy
> [3, 1, 4, 1, 5, 9, 2, 6]
> ###
> 
> 
> 
> > # What I need for this is and 'extract' function which retains
> > # the original reference so that when I code:
> > t[1] = 'three'
> > # list 'test looks like this:
> > [1, 2, 'three', 4, 5, 6, 7, 8, 9, 10]
> 
> Trying to do this with list comprehensions probably won't work: list
> comprehensions are spiritually designed NOT to modify the original list.
> *grin*
> 
> Instead, you may want do direct manipulations --- like indicing and del
> --- instead, and you should have better results.  In your original code,
> though, you did something like:
> 
> ###
> >>> test = [1,2,3,4,5,6,7,8,9,10]
> >>> t = mylib.extract(test,2)
> >>> print t
> ###
> 
> How about reassigning to 'test'?
> 
> 
> 
> Good luck!

-- 
Tim Johnson <tim at johnsons-web.com>
      http://www.alaska-internet-solutions.com



More information about the Tutor mailing list