# extract

Definition: | sequence res = extract(sequence source, indexes, integer invert=false)
Description: | Pick out a set of elements from a sequence according to the supplied set of indexes. source : the sequence from which to extract elements. indexes : a sequence of atoms, the indexes of the elements to be fetched in source. invert : invert the indexes, and/or force dword-sequence return, see notes below. Returns a sequence, of the same length as indexes.
pwa/p2js: | Supported.
Inversion: | Index inversion is difficult to explain. Typically you will either know that you need it (and why), or you simply don’t need it. The P-value correction task on rosettacode contains an example of use, in that case it is about putting things back where they belong after shuffling them about to do your thing (if you have a better explanation or example please feel free to pass it along). Instead of using the indexes directly, they are used to construct the indexes to use: each (index[i])’th index gets i. If indexes is {1,2,3} it behaves identically whether invert is true or not, because [1/2/3] get 1/2/3, which is the same. However if indexes is {3,1,2} then [3/1/2] get 1/2/3, and it behaves as if {2,3,1} had been passed (and invert was false). To clarify, `..,{3,1,2},true)` [re-]creates indexes as {0,0,0} -> {0,0,1} -> {2,0,1} -> {2,3,1}, before being used. Should invert be true(odd) but sort(indexes)!=tagset(length(indexes)) then I expect an error would probably ensue, not that I test for or can be adamantly certain of that. If invert is odd/true/1 extract() inverts the indexes as just explained. If invert is false/0/true/1 extract() returns a string when the source is one. If invert is any other non-zero value (eg 2 to avoid inversion) extract() returns a dword-sequence.
Auillary function: | sequence res = reinstate(sequence source, object indexes, replacements, bool invert=false) Allows (for example) some previously extracted elements to be replaced, not necessarily but usually in the same order/slots. Often also a useful way to initialise the first value or first few values of a freshly generated sequence. If indexes is an integer then replacements is the entire item to be put into that slot and invert must be false. if replacements is an atom or a sequence of length 1 (when wrong) it is treated as a sequence of that of the required length, otherwise a fatal error occurs should length(indexes)!=length(replacements), except as below. Special attention may need to be applied to the case when length(indexes) is 1 but other cases are relying on an implicit repeat of a length-1 replacements, in other words for a given fixed length-1 replacements and assuming {idx1,..idxN} works then you may need to pass idx and replacements or {idx} and {replacements} rather than {idx} and replacements. As ever, careful testing helps, see examples. If source is {} and indexes is a sequence, source is replaced with repeat(0,max(indexes)) and then (and only then) a replacements of {} is replaced with tagset(length(indexes)), before of course performing the same processing as above, which can be used to create reverse index lookups. For example reinstate({},{3,5,7},{}) returns {0,0,1,0,2,0,3}, ie res[3] is 1 which is the position where the 3 was in indexes. You could have just done a find(3,indexes) instead, but in some cases that might not scale quite so well, or if you would have needed to make a copy anyway, you might as well convert it. While the (reinstate) example below emulates reverse(), and in fact the same effect could be achieved by using that routine on either the indexes or the results from extract(), it is probably more likely that you would manipulate the results from extract() before using reinstate() to put them back in the same set of places but a different order. Note that the routine name replace() is already in use as an otherwise almost pointless compatibility routine for Euphoria, and obviously must not be confused with reinstate().
Examples: |
    ?extract({11,13,15,17},{3,1,2,1,4}) -- prints {15,11,13,11,17}
    string s = "nip"
    ?reinstate(s,{3,1},extract(s,{1,3})) -- prints "pin"
    sequence sieve = reinstate(repeat(true,12),1,false) -- {false,true,true,true...}
    sequence res = reinstate(repeat(0,12),{1,2},{1,1}) -- {1,1,0,0,0,0,0,0,0,0,0...}
    ?reinstate(repeat(0,12),{1,2},{1,1}) -- {1,1,0,0,0,0,0,0,0,0,0,0}
    ?reinstate(repeat(0,10),{1,2},{1}) -- {{1},{1},0,0,0,0,0,0,0,0}
    ?reinstate(repeat(0,12),{1,2},1) -- {1,1,0,0,0,0,0,0,0,0,0,0}
    ?reinstate(repeat(0,11),{1},{1}) -- {1,0,0,0,0,0,0,0,0,0,0} -- cf 2 lines above
    ?reinstate(repeat(0,10),1,{1}) -- {{1},0,0,0,0,0,0,0,0,0}
    ?reinstate(repeat(0,11),1,1) -- {1,0,0,0,0,0,0,0,0,0,0}
Implementation: | See builtins\pextract.e (an autoinclude) for details of the actual implementation.