xsharp.eu • Extract column from array
Page 1 of 1

Extract column from array

Posted: Mon Jul 18, 2022 10:12 am
by Jack@007
Hi,

I'm a little bit rusty in VO.

My question concerns a multi dimensional array like:

a:={}
AAdd(a, {'a1', 'b1', 'c1'})
AAdd(a, {'a2', 'b2', 'c2'})
AAdd(a, {'a3', 'b3', 'c3'})

Extracting a row from the array is easy.
b:={}
b:=a[2]

(b equal "a2", "b2", "c2" ).

What would be the most efficiënt way to extract a column from an array (so the "b1", "b2", "b3" values)?
I'm not getting further than a for next loop.

TIA

Jack

Extract column from array

Posted: Mon Jul 18, 2022 11:57 am
by wriedmann
Hi Jack,
this could be done in a similar way:

Code: Select all

b:={}
for nI := 1 upto ALen( a )
  AAdd( b, a[nI,2] )
next
Please not that this is not optimal code, it should only give you an idea.
If you need optimized code for this, please let me know.
Wolfgang

Extract column from array

Posted: Mon Jul 18, 2022 1:33 pm
by leon-ts
Hi Jack,
The following examples are not optimized, but visually simple:

Example 1

Code: Select all

LOCAL b := {} AS ARRAY // initialized array
AEval(a, {|x| AAdd(b, x[2])})
Example 2

Code: Select all

LOCAL b AS ARRAY // NULL_ARRAY
b := AEvalA(AClone(a), {|x| x[2]})
Best regards,
Leonid

Extract column from array

Posted: Mon Jul 18, 2022 1:54 pm
by Jack@007
Hi Wolfgang,

That approach is what i'm using now too.

Extract column from array

Posted: Mon Jul 18, 2022 1:55 pm
by Jack@007
Hi Leonid,

That's more the way i was looking for; a one liner to fill the new array.
Thanks.

Extract column from array

Posted: Mon Jul 18, 2022 1:59 pm
by wriedmann
Hi Jack,
if your arrays are small, the one liner works very well.
But if your arrays are larger, the one liners are using more memory.
Wolfgang

Extract column from array

Posted: Mon Jul 18, 2022 2:10 pm
by Jack@007
Hi Wolfgang,

The array i'm using has typical dimensions of 30x7 elements. I guess memory should be no problem. Correct me i i'm wrong.

Extract column from array

Posted: Mon Jul 18, 2022 2:21 pm
by wriedmann
Hi Jack,
with such small arrays that should not be a problem.
If the arrays become larger, creating the target array with the correct size helps a lot.
That would result in code like this:

Code: Select all

local nLen as dword
nLen := ALen( a )
b := ArrayNew( nLen )
for nI := 1 upto nLen
  b[nI] := a[nI,2]
next
Wolfgang

Extract column from array

Posted: Mon Jul 18, 2022 2:30 pm
by leon-ts
Guys,
I think the best option is to write a function. It will be optimal both in terms of speed and memory, and will also be readable when used in code (one line).

The fastest and most optimized variant of the function (as far as I know VO):

Code: Select all

FUNCTION ACol(aSource AS ARRAY, dwElement AS DWORD) AS ARRAY PASCAL
	
    LOCAL i, dwLen AS DWORD
    LOCAL aResult, aI AS ARRAY
	
    IF ( dwLen := ALen(aSource) ) > 0
        aResult := ArrayCreate(dwLen)
        FOR i := 1 UPTO dwLen
            aI := ArrayGet(aSource, i)
            ArrayPut(aResult, i, ArrayGet(aI, dwElement))
        NEXT
    ELSE
        aResult := {}
    ENDIF
	
    RETURN aResult
Applying the ACol function in code:

Code: Select all

LOCAL b AS ARRAY
b := ACol(a, 2)
Best regards,
Leonid