1. Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by euphoric (admin) Jul 22, 2015
- 1599 views
Is there a super-fast, super-easy way to remove an element based on a value found at a particular element's position? For example:
sequence s = { {"1",1},{"2",2},{"3",3} } -- not actual data s = remove( s, 1, "1" } --<-- remove the element from sequence s whose first element equals "1" -- s is now { {"2",2},{"3",3} }
I didn't find anything in the manual.
2. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by petelomax Jul 23, 2015
- 1549 views
that looks pretty easy, is there anything wrong with this?
function remove(sequence s, integer idx, object val) object si for i=1 to length(s) do si = s[i] if sequence(si) and idx<=length(si) and equal(si[idx],val) then s = s[1..i-1]&s[i+1..length(s)] exit end if end for return s end function
Edit: oops - replaced equal(si[i],val) with equal(si[idx],val)
it should of course be renamed something like "remove_element_with_specified_ith_value()"
3. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by euphoric (admin) Jul 23, 2015
- 1511 views
that looks pretty easy, is there anything wrong with this?
There's so much wrong with that code, but I don't have time to get into it.
HAHHAHAA!
Just kiddin'. I forgot about using 'exit' to break out. I was looping from end to beginning. Ugh.
Thanks!
4. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by Spock Jul 23, 2015
- 1514 views
that looks pretty easy, is there anything wrong with this?
There's so much wrong with that code, but I don't have time to get into it.
HAHHAHAA!
Just kiddin'. I forgot about using 'exit' to break out. I was looping from end to beginning. Ugh.
Thanks!
That example code removes one element if it finds a match. Is it possible there might be more than one to be removed? This was kinda implied by the question but not stated outright. It's good to clarify these things..
Spock
5. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by DerekParnell (admin) Jul 24, 2015
- 1513 views
--** -- Removes an element from a sequence when that element contains the target -- -- Parameters: -- # ##Source## : a sequence to be checked for the target. -- # ##Target## : an object, the leftmost element containing this target value is removed. -- # ##Index## : an integer. If greater than zero, it specifies the index -- at which the target must be found in the elements. If -- zero, then the target can be found at any location in the -- elements. -- -- Returns: -- A **sequence** that is identical the the source but without the leftmost -- element that had contained the target value. -- -- Comments: -- * This only removes, at most, one element. -- * All atom elements are ignored, and thus never removed. -- * If the target is not located, the original sequence is returned. -- -- Examples: -- <~eucode> -- -- The second element is removed because its first element is 3 -- ? locate_remove({ {4,3}, {3,2}, {1}, 3}, 3, 1) --> { {4,3}, {1}, 3} -- sequence Data -- Data = { -- {"Bob","Carroll","Orange"}, -- {"Derek","Parnell","Blue"}, -- {"Iris","Lander","Red"} -- } -- -- Remove the element that contains "Parnell" as its second element. -- Data = locate_remove(Data, "Parnell", 2) -- ? Data --> -- -- { -- -- {"Bob","Carroll","Orange"}, -- -- {"Iris","Lander","Red"} -- -- } -- <~/eucode> public function locate_remove(sequence pSource, object pTarget, integer pIndex=1) sequence lSample -- Mild sanity check first. if pIndex < 0 then return pSource end if -- Algorithm when the target must be at a specific location in the elements. if pIndex >= 1 then -- Potentially need to check each element in the source parm. for i = 1 to length(pSource) do -- But only sequence elements if sequence (pSource[i]) then -- Take a reference copy for speed. Avoids multiple de-indexing. lSample = pSource[i] -- Only look at elements that can possibly contain the target. if length(lSample) >= pIndex then -- A simple equality test to check the that we have the target in this element. if equal(pTarget, lSample[pIndex]) then -- Shift remaining elements down, obliterating the element that -- contains the target. This avoids duplicating the whole sequence. pSource[i .. $-1] = pSource[i+1 .. $] -- return the sequence minus the target, -- and thus stop looking any more. return pSource[1 .. $-1] end if end if end if end for -- Didn't find the target anywhere, so return the source unchanged. return pSource end if -- Algorithm when the target can be anywhere in the elements. -- Potentially need to check each element in the source parm. for i = 1 to length(pSource) do -- But only sequence elements if sequence (pSource[i]) then -- Find the target in this element. if find(pTarget, pSource[i]) != 0 then -- Shift remaining elements down, obliterating the element that -- contains the target. This avoids duplicating the whole sequence. pSource[i .. $-1] = pSource[i+1 .. $] -- return the sequence minus the target, -- and thus stop looking any more. return pSource[1 .. $-1] end if end if end for -- Didn't find the target anywhere, so return the source unchanged. return pSource end function -- Define the unit tests for this function. ifdef UNITTESTS then -- Only invoke them if we are running with unit testing turned on. include std/unittest.e procedure _tester() sequence lBase lBase = { {1}, {2,3}, 3, {3,4}, {}, {5,6,7}, {3,5} } -- Stupid index parameter. test_equal("A Low", lBase, locate_remove(lBase, 3, -1)) test_equal("A High", lBase, locate_remove(lBase, 3, 9999999)) -- Specific index checks. test_equal("B1", { {1}, {2,3}, 3, {}, {5,6,7}, {3,5} }, locate_remove(lBase, 3, 1)) test_equal("B2", { {1}, {2,3}, 3, {}, {5,6,7}, {3,5} }, locate_remove(lBase, 3)) -- Use default index. test_equal("C", { {1}, 3, {3,4}, {}, {5,6,7}, {3,5} }, locate_remove(lBase, 3, 2)) test_equal("D", lBase, locate_remove(lBase, 3, 3)) test_equal("E", lBase, locate_remove(lBase, -11)) test_equal("F", lBase, locate_remove(lBase, `3`)) test_equal("G", {}, locate_remove({}, 3)) test_equal("H", { {1}, {2,3}, 3, {3,4}, {}, {3,5} }, locate_remove(lBase, 7, 3)) -- Target can be anywhere in the elements. test_equal("I", { {1}, 3, {3,4}, {}, {5,6,7}, {3,5} }, locate_remove(lBase, 3, 0)) test_equal("J", { {1}, 3, {3,4}, {}, {5,6,7}, {3,5} }, locate_remove(lBase, 2, 0)) test_equal("K", { {2,3}, 3, {3,4}, {}, {5,6,7}, {3,5} }, locate_remove(lBase, 1, 0)) test_equal("L", { {1}, {2,3}, 3, {3,4}, {}, {3,5} }, locate_remove(lBase, 7, 0)) test_equal("M", lBase, locate_remove(lBase, 0, 0)) end procedure _tester() test_report() end ifdef
6. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by ghaberek (admin) Jul 24, 2015
- 1487 views
That example code removes one element if it finds a match. Is it possible there might be more than one to be removed? This was kinda implied by the question but not stated outright. It's good to clarify these things..
Maybe I'm over-thinking things, but here's my take on the algorithm...
public constant LT = -1, -- less than EQ = 0, -- equal to GT = 1, -- greater than NE = {LT,GT}, -- not equal to $ -- -- Remove items from 's' where s[n][index] is 'ops' (e.g. EQ) to 'value'. -- -- Note: to compare the whole item, set 'index' to 0. -- public function remove_where( sequence s, integer index, object value, object ops = EQ, integer limit = 0 ) integer n, count, cmp, op1, op2 n = 1 count = 0 if atom( ops ) then op1 = ops op2 = ops else op1 = ops[1] op2 = ops[2] end if while n <= length( s ) do if atom( s[n] ) or length( s[n] ) < index then -- skip invalid items n += 1 continue end if if index = 0 then -- compare the whole item cmp = compare( s[n], value ) else -- compare the index of item cmp = compare( s[n][index], value ) end if if cmp = op1 or cmp = op2 then -- remove the matching item s = remove( s, n ) count += 1 if count = limit then -- stop processing exit end if else -- move to the next item n += 1 end if end while return s end function
Example:
include std/console.e sequence s = { {"1",1}, {"2",2}, {"3",3}, {"4",4}, {"5",5}, {"6",6} } -- remove any item starting with "1" s = remove_where( s, 1, "1" ) display( s ) -- remove the first item less than or equal to "3" s = remove_where( s, 1, "3", {LT,EQ}, 1 ) display( s ) -- remove everything not equal to "4" s = remove_where( s, 1, "4", {LT,GT}, 0 ) display( s )
Output:
{ {"2",2}, {"3",3}, {"4",4}, {"5",5}, {"6",6} } { {"3",3}, {"4",4}, {"5",5}, {"6",6} } { {"4",4} }
-Greg
7. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by ghaberek (admin) Jul 24, 2015
- 1511 views
Maybe I'm over-thinking things, but here's my take on the algorithm...
--** -- Removes an element from a sequence when that element contains the target -- -- Parameters: -- # ##Source## : a sequence to be checked for the target. -- # ##Target## : an object, the leftmost element containing this target value is removed. -- # ##Index## : an integer. If greater than zero, it specifies the index -- at which the target must be found in the elements. If -- zero, then the target can be found at any location in the -- elements. -- -- Returns: -- A **sequence** that is identical the the source but without the leftmost -- element that had contained the target value. -- -- Comments: -- * This only removes, at most, one element. -- * All atom elements are ignored, and thus never removed. -- * If the target is not located, the original sequence is returned. -- -- Examples: -- <~eucode> -- -- The second element is removed because its first element is 3 -- ? locate_remove({ {4,3}, {3,2}, {1}, 3}, 3, 1) --> { {4,3}, {1}, 3} -- sequence Data -- Data = { -- {"Bob","Carroll","Orange"}, -- {"Derek","Parnell","Blue"}, -- {"Iris","Lander","Red"} -- } -- -- Remove the element that contains "Parnell" as its second element. -- Data = locate_remove(Data, "Parnell", 2) -- ? Data --> -- -- { -- -- {"Bob","Carroll","Orange"}, -- -- {"Iris","Lander","Red"} -- -- } -- <~/eucode>
I guess I'm not over-thinking this; Derek's code certainly looks more impressive. My code will process atom items (set index = 0 to compare atoms) plus it will compare items of any given equality (e.g. less than).
-Greg
8. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by euphoric (admin) Jul 24, 2015
- 1467 views
That example code removes one element if it finds a match. Is it possible there might be more than one to be removed? This was kinda implied by the question but not stated outright. It's good to clarify these things..
In my particular use-case, there would only ever be one matching record. However, you're right. There might be a need to eliminate all records matching the criteria.
Thank you for the additional code, Derek and Greg! And everybody else who has contributed or will contribute.
9. Re: Algorithm to Remove An Element Based on Value of Particular Element Position
- Posted by BRyan Jul 24, 2015
- 1446 views
Would this work ?
sequence s s = { {"1",1},{"2",2},{"3",3} } function Remove( object o, sequence seq ) -- atom p -- if atom( o ) then p = find(o,seq) else p = match(o,seq) endif -- if not p then return seq elsif p = 1 then return seq[1+sizeof(o)-1..$] else return seq[1..p-1]&seq[+1+sizeof(o)..$] end if end function