[Solved] Removing One Item from an Array Variable

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
rtellshow
Posts: 15
Joined: Tue Apr 13, 2010 8:46 am

[Solved] Removing One Item from an Array Variable

Post by rtellshow »

Finding it hard to figure this out. So thanks in advance.

Lets say I have:
startArray = array(1,2,3,4,5)

I want either:
startArray(3) with the elements 1,2,4,5 or
newArray(3) with the elements 1,2,4,5

Is there anything like:
startArray(2).Remove ????

Can I used Redim preserve to preserve all but one element?

Or do I need to dump everything into a string, process the string, and then dump it back into an array?
Last edited by rtellshow on Mon Jun 04, 2018 11:24 pm, edited 1 time in total.
OpenOffice 4.1.3 on Windows 10
User avatar
Villeroy
Volunteer
Posts: 31269
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: Removing One Item from an Array Variable

Post by Villeroy »

With Python as macro language you have the full power of a mature programming language, including lots of functions for array manipulation. With Basic you have to write a loop which appends the wanted items to the new array.
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
User avatar
Lupp
Volunteer
Posts: 3542
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: Removing One Item from an Array Variable

Post by Lupp »

Code: Select all

Function removeFrom1DarrayByIndex(p1Darray, pIndex As Long) As Boolean
removeFrom1DarrayByIndex = False
On Error Goto errorExit
l = Lbound(p1Darray) : u = Ubound(p1Darray)
For j = pIndex To u - 1
    p1Darray(j) = p1Darray(j + 1)
Next j
Redim Preserve p1Darray(l To u - 1)
removeFrom1DarrayByIndex = True
errorExit:
End Function

Sub test
a = Array(1,2,3,4,5)
Print removeFrom1DarrayByIndex(a, 2)
REM Inspect a in the 'Watch' window of the Basic IDE.
End Sub
Be careful. If the array the function operates on is referenced by additional variables the Redim will create a new array only referenced by the variable passed to the function. additional unexpected results may occur.
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
rtellshow
Posts: 15
Joined: Tue Apr 13, 2010 8:46 am

Re: [Solved] Removing One Item from an Array Variable

Post by rtellshow »

Villeroy...I guess I need to take on Python....

In the mean time I'll just use Lupp's code....does the job quite efficiently.

Thanks
OpenOffice 4.1.3 on Windows 10
JeJe
Volunteer
Posts: 2763
Joined: Wed Mar 09, 2016 2:40 pm

Re: [Solved] Removing One Item from an Array Variable

Post by JeJe »

An alternative to an array is to use the collection object - which does allow easy removal of items.

Code: Select all


Dim test 
Set test = New Collection

for i = 1 to 5
  test.Add(i) 
next


test.remove(3)

for i = 1 to test.count
msgbox test.item(i)
next


Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
User avatar
Lupp
Volunteer
Posts: 3542
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: [Solved] Removing One Item from an Array Variable

Post by Lupp »

If you (rtellshow) actually want to use one-dimensional arrays, I would suggest you replace the above given code by:

Code: Select all

Function removeFrom1DarrayByIndex(p1Darray, pIndex As Long) As Boolean
removeFrom1DarrayByIndex = False
On Error Goto errorExit
l = Lbound(p1Darray) : u = Ubound(p1Darray)
h = p1Darray(u)
Redim Preserve p1Darray(l To u - 1) 
REM Creates a new array. Disposes the original if no references are left.
For j = pIndex To u - 2
    p1Darray(j) = p1Darray(j + 1)
Next j
p1Darray(u - 1) = h
removeFrom1DarrayByIndex = True
errorExit:
End Function

Sub test
a = Array(1,2,3,4,5)
b = a
Print removeFrom1DarrayByIndex(a, 2)
REM Inspect a and b in the 'Watch' window of the Basic IDE.
End Sub

The slightly reworked function will still create a new instance of the array with one element less, but it will not at all afflict now the original array if there were additional variables referencing it. The roughly sketched version I gave first would mess the original up.
(If there was only one referencing variable, the original will be disposed anyway.)

The suggestion by "jeje" should be preferrable in many cases. During development of code in the IDE a little problem may be that you cannot view the elements in the 'Watch'.
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
JeJe
Volunteer
Posts: 2763
Joined: Wed Mar 09, 2016 2:40 pm

Re: [Solved] Removing One Item from an Array Variable

Post by JeJe »

One thing I often do is instead of keeping resizing the array is to have a buffer at the end of the array so that's unnecessary.

Code: Select all





Sub test

	startArray = array(1,2,3,4,5,0,0,0,0,0)
	ubbuffer = 9
	ubarray = 4

	'remove second item in the array = 3
	item = 2
	for i = item to ubarray - 1
		startArray(i)= startArray(i+1)
	next
	ubarray = ubarray - 1

	'for i = 0 to ubarray 'show the bit of the array we're using
	'msgbox startArray(i)
	'next

	'removing the last item is easy, its just this
	ubarray = ubarray - 1

	'for i = 0 to ubarray 'show the bit of the array we're using
	'msgbox startArray(i)
	'next

	'adding an item to the end is also easy
	ubarray = ubarray + 1
	startArray(ubarray) = 5

	'for i = 0 to ubarray 'show the bit of the array we're using
	'msgbox startArray(i)
	'next

	'put the 3 back - that means moving items
	item =2
	ubarray = ubarray + 1
	for i = ubarray to item +1 step -1
		startArray(i)= startArray(i-1)
	next
	startArray(2) = 3

	for i = 0 to ubarray 'show the bit of the array we're using
		msgbox startArray(i)
	next

End Sub


(Windows has an api function called Copymemory which enables fast movement of items in an array. In my experiments with it in OOBasic it didn't work with anything except the first item in the array unfortunately.)

Edit: You only need to redim if the size of the buffer is going to be exceeded.

If the order of the items in the array is unimportant then all you have to do is swap the item you want to remove with the last item and removing and adding items is always really easy.

Code: Select all


startArray(itemposition) = startArray(ubarray) 
ubarray=ubarray-1
Edit2:

If the order of the items in the array is unimportant then you could use the same trick with redimensing the array of course - just swap the item you want to remove with the last item and redim preserve to the smaller size.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
User avatar
Lupp
Volunteer
Posts: 3542
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: [Solved] Removing One Item from an Array Variable

Post by Lupp »

To keep a buffer and to manage the used size explicitly is clearly a good idea in many cases. However, the Redim Preserve command, even if NOT actually changing the size, has the additional effect of detaching the redimensioned variable (in fact a pointer to a newly created array then) from other variables referencing the original array. That was the reason for what I placed the Redim Preserve above the statements changing contents in the reworked version of my code.

@JeJe: I also do not know a way in Basic to access the actual storage of an array. As I did a bit of "real programming" in Pascal mainly, I am missing the feasibility of absolute declarations heavily. I am aware, of course, of the rsiks and challenges coming with the concept in a (next to) untyped programming language. Variant arrays will not have a contiguous storage range as their data container at all in most cases, and will therefor not be eligible for real access. Having the facility only for strictly typed arrays of numeric data would anyway be helpful. Please tell me if you find a way.
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
JeJe
Volunteer
Posts: 2763
Joined: Wed Mar 09, 2016 2:40 pm

Re: [Solved] Removing One Item from an Array Variable

Post by JeJe »

Lupp - try this - it doesn't work so I presume that OO arrays don't store items in contiguous memory. Visual Basic 6 has the VarPtr function for accessing memory locations - but OOBasic doesn't have that. You lose cross platform compatability with Windows specific code anyway and its going beyond what OO is meant for.

Code: Select all

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cbCopy As Long)
Sub Main
dim ar() as long
redim ar(10)
ar(3) = 60
ar(4) = 80
copymemory ar(0),ar(3),8
msgbox ar(0) '60 as should be
msgbox ar(1) 'should be 80 but returns 0

End Sub

Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
RPG
Volunteer
Posts: 2250
Joined: Tue Apr 14, 2009 7:15 pm
Location: Netherlands

Re: [Solved] Removing One Item from an Array Variable

Post by RPG »

I think we can better ask to the OP why he does need to remove an item of an array. Also important is maybe to place an example. An example makes more clear.

Romke
LibreOffice 7.1.4.2 on openSUSE Leap 15.2
JeJe
Volunteer
Posts: 2763
Joined: Wed Mar 09, 2016 2:40 pm

Re: [Solved] Removing One Item from an Array Variable

Post by JeJe »

@Lupp This works if that's ever any use to you.

Code: Select all



dim st as string,st2 as string

st = "Fish"
st2 = "XXXX"

copymemory st2,st,2
msgbox st2 'FiXX
@RPG

Its solved... me and Lupp are just digressing...
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
RPG
Volunteer
Posts: 2250
Joined: Tue Apr 14, 2009 7:15 pm
Location: Netherlands

Re: [Solved] Removing One Item from an Array Variable

Post by RPG »

JeJe wrote:Its solved... me and Lupp are just digressing...
I do trust your examples and also the examples of Lupp. I want have an example of the original problem there the examples of you and also the examples of Lupp do not expand knowledge of the API. Then using Python or Collection is better.

Romke
LibreOffice 7.1.4.2 on openSUSE Leap 15.2
Post Reply