Is it possible to unpack an array

246 views
Skip to first unread message

Eric Lendvai

unread,
Feb 5, 2021, 6:24:01 AM2/5/21
to Harbour Users

In Python it is possible to assign all the element of an array to a series of variable in a single assignment statement.
Let's say we have a function that returns an array. Is there a method to extract all the cells without the need of a temporary array? Any tricks using variable references ?
Here is an example:

function main()
local aResult
local iCell1,iCell2,iCell3

aResult := FunctionReturningArray()
iCell1 := aResult[1]
iCell2 := aResult[2]
iCell3 := aResult[3]

//The following would be valid in Python and is called "unpacking" an array.
iCell1,iCell2,iCell3 := FunctionReturningArray()

?"iCell1=",iCell1
?"iCell2=",iCell2
?"iCell3=",iCell3

return nil

function FunctionReturningArray()
return {1,2,3}

mstuff kstuff

unread,
Feb 5, 2021, 10:11:41 AM2/5/21
to Harbour Users

Eric,

Do you just want to dump the array and any sub-arrays within?

MikeK

Eric Lendvai

unread,
Feb 5, 2021, 2:13:28 PM2/5/21
to Harbour Users
Hello Mike,
Only the first level of the array.
Thanks.

Miroslav Georgiev

unread,
Feb 5, 2021, 5:10:26 PM2/5/21
to Harbour Users
I use hash instead...

mstuff kstuff

unread,
Feb 5, 2021, 10:10:15 PM2/5/21
to Harbour Users
This may give you some ideas:
and then do a do while or a for len(array_name)...

Hope that maybe useful.

I have my other unfinished source code that does do whiles but, hit a major road block when I couldn't find a way to display the contents of an array "code block".
MikeK

Eric Lendvai

unread,
Feb 15, 2021, 1:19:42 AM2/15/21
to Harbour Users
Just made a pull request in Harbour to add a function hb_AUnpack().
This will give a functionality that is similar to what I was asking about, sadly not the same exact syntax.

// hb_AUnpack will assign all the element of the first parameter if is an array, to following parameters passed by reference.
// This provides the concept of "unpacking" an array as used in the Python language.
// This function is very useful when the first parameter is a function returning an array.
// For example you could return {<lResult>,<cErrorMessage>}
//    if !hb_AUnpack(FunctionReturningAnArray(),,@cLastError)
//        ?"Error Occurred calling FunctionReturningAnArray:",cLastError
//    endif
// Will return the first element of the array as well as placing it in 2nd parameter, if specified by reference.
HB_FUNC( HB_AUNPACK )
{
    PHB_ITEM pArray = hb_param( 1, HB_IT_ARRAY );
    if( pArray )
    {
        HB_USHORT uiLen = ( HB_USHORT ) hb_arrayLen(pArray);
        HB_USHORT uiIter;
        HB_USHORT uiArgCount = ( HB_USHORT ) hb_pcount();

        for( uiIter = 1; uiIter <= HB_MIN(uiLen,uiArgCount-1); uiIter++ )
        {
            if ( HB_ISBYREF( uiIter+1 ) )
            {
                PHB_ITEM pArrayElement = hb_itemNew( NULL );
                hb_arrayGet( pArray, (HB_ULONG) uiIter, pArrayElement ) ;
                hb_itemParamStore( uiIter+1, pArrayElement );
                hb_itemRelease( pArrayElement );
            }
            if ( uiIter == 1 )
            {
                PHB_ITEM pFirstArrayElement = hb_itemNew( NULL );
                hb_arrayGet( pArray, (HB_ULONG) uiIter, pFirstArrayElement ) ;
                hb_itemReturn( pFirstArrayElement );
            }
        }
    }
}

Appliserver

unread,
Feb 15, 2021, 3:17:41 AM2/15/21
to harbou...@googlegroups.com

Maybe:

iCell1:=FunctionReturningArray()[1]

Dan

--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/0bce28f6-43b6-4529-9bfb-89f37ae8a980n%40googlegroups.com.

Eric Lendvai

unread,
Feb 15, 2021, 5:50:10 AM2/15/21
to harbou...@googlegroups.com
Hello Dan,

The issue is to extract multiple array elements at one time.

In python this could be done via something like (not the commas to the left of the assignment sign):
iCell1, iCell2, iCell3 =  FunctionReturningArray()

So the closest I was able to do is the following:
hb_AUnpack(FunctionReturningArray(), @iCell1, @iCell2, @iCell3)
same as
iCell1 :=  hb_AUnpack(FunctionReturningArray(), , @iCell2, @iCell3)  

Eric

You received this message because you are subscribed to a topic in the Google Groups "Harbour Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/harbour-users/EuRbfhmI3TQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to harbour-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/harbour-users/2be991f8-848f-6082-8113-2a155ef00397%40appliserver.com.

Aleksander Belov

unread,
Feb 15, 2021, 6:09:33 AM2/15/21
to harbou...@googlegroups.com

Or else ...


AEVal( { @iCell1, @iCell2, @iCell3}, {|a,ix| FunctionReturningArray()[ix] } )

Alex ...


15.02.2021 12:49, Eric Lendvai пишет:

José M. C. Quintas

unread,
Feb 15, 2021, 7:36:23 AM2/15/21
to harbou...@googlegroups.com

You forgot the assign.

Another option, because may be function can't be called more than one time:


PROCEDURE Main

   LOCAL a, b, c

   //AEval( { @a, @b, @c }, { | a, nItem | a := MyArray()[ nItem ] } )

   hb_AUnpack( MyArray(), @a, @b, @c )

   ? a
   ? b
   ? c
   Inkey(0)

   RETURN

FUNCTION MyArray()

   RETURN { 10, 20, 30 }

FUNCTION hb_AUnpack( aList, a, b, c, d )

   IF ValType( aList ) != "A"
      RETURN Nil
   ENDIF
   IF Len( aList ) > 0;   a := aList[ 1 ]; ENDIF
   IF Len( aList ) > 1;   b := aList[ 2 ]; ENDIF
   IF Len( aList ) > 2;   c := aList[ 3 ]; ENDIF
   IF Len( aList ) > 3;   d := aList[ 4 ]; ENDIF

   RETURN Nil

José M. C. Quintas

Aleksander Belov

unread,
Feb 15, 2021, 8:38:26 AM2/15/21
to harbou...@googlegroups.com

Thanks José !

And if like this ...


PROCEDURE Main

 LOCAL a, b, c,  aA

 AEval( { @a, @b, @c }, { | a, nItem | a := aA[ nItem ] }, (aA:=MyArray()), Len(aA) )

//    hb_AUnpack( MyArray(), @a, @b, @c )



   ? a
   ? b
   ? c

   Inkey(0)

RETURN

FUNCTION MyArray()

   RETURN { 10, 20, 30 }


:-)

Alex


15.02.2021 14:36, José M. C. Quintas пишет:

Eric Lendvai

unread,
Feb 15, 2021, 11:17:23 AM2/15/21
to harbou...@googlegroups.com
Thanks José.
That is why I made it in C and proposed it as a merge in Harbour.
I also return the first element of the array, to make it easier in case you want to test the result.
Eric


Hurricane

unread,
Feb 15, 2021, 11:52:16 AM2/15/21
to Harbour Users
only one variable is needed. Your example is exaggerated, unnecessary.

local aResult
local uItem

aResult := FunctionReturningArray()

? aResult[1]
? aResult[2]
? aResult[3]

for each uItem in FunctionReturningArray()
   ? uItem
next

AEVAL(FunctionReturningArray(), {|u| QOUT(u) })

Sem precisar procurar pelo em ovo.

oleksa

unread,
Feb 15, 2021, 2:58:21 PM2/15/21
to harbou...@googlegroups.com
Hi!

Try the next code, (i trying to keep the syntax style like in python)
=====================================================
#command <xVar,...> UNPACKING <arr> =>;
  __mvPrivate( "i" );;
  FOR EACH i IN {<(xVar)>};;
     __mvPrivate( i );;
     __mvPut( i, iif( Len( <arr> ) >= i:__enumIndex, <arr>\[i:__enumIndex], nil ) );;
  NEXT;;
  __mvRelease( "i" )


proc main

  iCell1, iCell2, iCell3, iCell4 UNPACKING FunctionReturningArray()

  iCell5 UNPACKING FunctionReturningArray()

  ?iCell1
  ?iCell2
  ?iCEll3
  ?iCell4
  ?iCell5

  return

function FunctionReturningArray()

  return {1,2,3}
===================================================================

Regards,
Oleksii Myronenko

5 лютого 2021, 13:24:05, від "Eric Lendvai" <ericl...@gmail.com>:

--
--
You received this message because you are subscribed to the Google
Groups "Harbour Users" group.
Unsubscribe: harbour-user...@googlegroups.com
Web: http://groups.google.com/group/harbour-users

---
You received this message because you are subscribed to the Google Groups "Harbour Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to harbour-user...@googlegroups.com.

hmpaquito

unread,
Feb 16, 2021, 4:49:42 AM2/16/21
to Harbour Users
My unpacking:

#Define Var1 a[1]
#Define Var2 a[2]
#Define Var3 a[3]

a:= {"hola", 34, date()}
? Var1
? Var2
? Var3
Reply all
Reply to author
Forward
0 new messages