Similar Threads
1. Perl style splice functions for VB.NET and VBA
I have been frustrated for a while by the difficulty of manipulating
arrays in VBA and VB.NET -- in particular the awkwardness involved
in appending, prepending, or inserting new elements -- so to make
my life easier I wrote two functions that act something like Perl's
splice function. I wrote the VBA version first, and then a slightly
different version for VB.NET. Both versions are included here,
and they are both a little different from the Perl function, but
close enough that you should be able to make them functionally
identical without too much trouble if you happen to feel like it.
What the functions do is chop zero or more elements out of an input
array (which can be of any type) at a specified location, and then
splice zero or more new elements into the array at the same location,
all in a single function call. Note that in the VB.NET version
the input array isn't changed, while in the VBA version (like in the
Perl function) it is. (Note also that VB.NET version is the simpler
of the two, since I didn't have to worry about arrays having
something other than zero as a lower bound).
Here are some sample calls (VB.NET version):
Dim qqq() as String = {"aaa", "bbb", "ccc"} 'Input array for the examples.
ArraySplice(qqq, 0, 0, "xxx") '= {"xxx", "aaa", "bbb", "ccc"}
ArraySplice(qqq, -1, 0, "xxx") '= {"aaa", "bbb", "ccc", "xxx"}
ArraySplice(qqq, 1, 1) '= {"aaa", "ccc"}
ArraySplice(qqq, 1, 1, "xxx", "yyy") '= {"aaa", "xxx", "yyy", "ccc"}
ArraySplice(qqq, 5, 0, "xxx", "yyy") '= {"aaa", "bbb", "ccc", "", "", "xxx", "yyy"}
I'm sure others have done the same thing I've done here, but I
haven't come across any examples so far, so I'm posting this in
the hope that: 1) someone else might find these functions useful;
and 2) if there are any bugs in my code or mistakes in my approach
someone will notice and let me know. Thanks in advance for any
comments!
One thing in particular: I needed to use generics for the VB.NET
version of the function (.NET Framework 2.0, actually), and this
was new to me, so I especially want to make sure this works properly
for everyone, no matter what framework version they are using or
how they have their environment configured. I was a little surprised
that function calls could omit the "Of" clause, even though it is
part of the function definition! This certainly makes using the
function simpler, but it's it's not clear to me why this is OK, so
it would be be very reassuring if someone could point me to a piece
of documentation that officially says this is allowed.
====== Start of VB.NET version of ArraySplice =====
'A VB splice function inspired by the one in Perl, although with a couple of differences.
'A copy is made of "arrayIn", "length" elements beginning at index "offset" are removed and replaced
'with the contents of "list", and then the copy is returned. The original input array is not modified.
'If "offset" is negative then nothing is removed, and new elements are appended to the end of the array.
'(Note: there is no need to explicitly supply the "Of" clause when calling this function).
Public Function ArraySplice(Of T)( _
ByVal arrayIn As T(), _
ByVal offset As Integer, _
ByVal length As Integer, _
ByVal ParamArray list As Object()) As T()
arrayIn = arrayIn.Clone 'To protect the input array -- if you want arrayIn to be ByRef then remove.
'=== Test and adjust arguments.
If offset < 0 Then
offset = arrayIn.Length 'A negative offset means append to end.
ElseIf offset > arrayIn.Length Then
ReDim Preserve arrayIn(offset - 1) 'A large offset will extend the array.
End If
If length < 0 Then
Throw New ArgumentOutOfRangeException("length", "Value cannot be less than 0")
ElseIf length > arrayIn.Length - offset Then
length = arrayIn.Length - offset 'Can't remove more elements than you've got!
End If
'=== Now do the actual splicing.
If list.Length > length Then 'arrayIn has to get bigger.
Dim saveUBound As Integer = UBound(arrayIn)
ReDim Preserve arrayIn(UBound(arrayIn) + list.Length - length)
For i As Integer = saveUBound To offset + length Step -1
arrayIn(i + list.Length - length) = arrayIn(i)
Next
ElseIf list.Length < length Then 'arrayIn has to get smaller.
For i As Integer = offset + length To UBound(arrayIn)
arrayIn(i + list.Length - length) = arrayIn(i)
Next
ReDim Preserve arrayIn(UBound(arrayIn) + list.Length - length)
End If
'Copy new values to arrayIn.
For i As Integer = 0 To UBound(list)
arrayIn(offset + i) = list(i)
Next
ArraySplice = arrayIn
End Function
====== Start of VBA version of ArraySplice =====
'This is a Perl style Splice function (for dynamic arrays only!). It works by doing a ReDim on the input array and appropriately copying array elements.
'It differs from Perl in returning the altered input array, not the spliced elements, and in that a negative offset just means append to end, not count backwards from end.
'(Note that because the input array is altered by ReDim, but never replaced, LBound(arrayIn) remains unchanged).
Public Function ArraySplice(arrayIn As Variant, Optional ByVal offset As Integer = 0, Optional ByVal length As Integer = 0, Optional list As Variant) As Variant
If IsMissing(list) Then list = Array()
'=== First test, and possibly adjust, the input arguments.
If Not IsArray(arrayIn) Then Err.Raise 5
If Not IsArray(list) Then Err.Raise 5
If offset < 0 Then
offset = UBound(arrayIn) + 1 - LBound(arrayIn)
ElseIf offset > UBound(arrayIn) + 1 - LBound(arrayIn) Then
ReDim Preserve arrayIn(LBound(arrayIn) To LBound(arrayIn) + offset - 1)
End If
If length < 0 Then
Err.Raise 5 '(It would actually make sense to allow negative values for length, but it would just be too much trouble to implement for too little value).
ElseIf length > UBound(arrayIn) + 1 - (LBound(arrayIn) + offset) Then
length = UBound(arrayIn) + 1 - (LBound(arrayIn) + offset) 'Can't remove more than you've got, so adjust the value of length,
End If
Dim arrayInLen As Integer, listLen As Integer, i As Integer
arrayInLen = UBound(arrayIn) + 1 - LBound(arrayIn)
listLen = UBound(list) + 1 - LBound(list)
'If the output should be a zero length array then throw an error, because there is no reliable way to make this happen in VBA.
'(You can't use ReDim to create a zero length array, and you can't even always set arrayIn = Array()).
If UBound(arrayIn) + listLen - length < LBound(arrayIn) Then Err.Raise 5
'=== Now we can do the actual splicing.
'Expand or reduce the size of the array, and shift the elements not being removed appropriately.
If listLen > length Then
Dim originalUBound As Integer
originalUBound = UBound(arrayIn)
ReDim Preserve arrayIn(LBound(arrayIn) To UBound(arrayIn) + listLen - length)
For i = originalUBound To LBound(arrayIn) + offset + length Step -1
arrayIn(i + listLen - length) = arrayIn(i)
Next
ElseIf listLen < length Then
For i = LBound(arrayIn) + offset + length To UBound(arrayIn)
arrayIn(i + listLen - length) = arrayIn(i)
Next
ReDim Preserve arrayIn(LBound(arrayIn) To UBound(arrayIn) + listLen - length)
End If
For i = LBound(list) To UBound(list)
arrayIn(LBound(arrayIn) + offset + i - LBound(list)) = list(i)
Next
ArraySplice = arrayIn
End Function
====== End of ArraySplice versions =====
--
John Brock
XXXX@XXXXX.COM
2. Trying to splice.... - Perl
3. splicing an array
Hi all,
I've an array of about 300 elements. I want to splice 7 elements at the
time, process this and then splece another 7 elemnts untill the end:
first ploblem if I use the scann_array function, perl say:
main::scann_array() called too early to check prototype at
G:\addresse\scrape.pl line 36.
and I don't know what that mean.
Ok I changed this an call splice in the while loop,
my ($name,$rub,$nl,$addr,$map,$tet,$capital) = splice(@a, 0,6);
but then perl says:
Use of uninitialized value in concatenation (.) or string at
G:\addresse\scrape.pl line 37, <FILE> line 106.
106 is the last line of the file, and this error appear at the end of
the execution, many times, but also in the middle of the output
Thanks.
Xbiton
----------------------------------
my @file = glob("*.eu");
foreach my $f (@file){
open(FILE, "$f");
my @a =();
@a =<FILE>;
my $count =@a;
while(@a){
my ($name,$rub,$nl,$addr,$map,$tet,$capital) =
scann_array(@a);
print "$name,$rub,$nl,$addr,$map,$tet,$capital";
}
}
sub scann_array(\@){
return splice(@{$_[0]},0,6);
}
4. Complicated Use of Splice - Perl
5. Dynamic Splice
I have the following line of code:
$MyPrtLine = join( ",", (split (/ *\t */, $_))[9,10,11,15,25,28,31,32,34] );
Is there a way to build splice portion: [9,10,11,15,25,28,31,32,34] so I could place as a variable either like:
$MyPrtLine = join( ",", (split (/ *\t */, $_))[${MySplic}] );
or
$MyPrtLine = join( ",", (split (/ *\t */, $_))${MySplice} );
Both generate errors and what I am after is the ability to make an external value which I have as part of an ini file which I read in. I then generate the splice and no code changes.
I am taking a large line ( 50+ fields ) and cutting down to what another user actually needs.
Any way to accomplish?
Thanks.
Wags ;)
ps here is code that works with the first line(ie static splice). You should be able to cut and paste unless your mailer changes tabs to spaces. I ran it and it worked on xp, as 810 - 5.8.4.
#!perl
use strict;
use warnings;
while ( <DATA> ) {
chomp;
printf "%s\n",
join( ",", (split (/ *\t */, $_))[9,10,11,15,25,28,31,32,34] );
}
__DATA__
VPkr dx 6694 V 3 E o vHbUNJq -75581.96 jZJy Z 13421216 sNvpbcSzF SVkecw djNTwqWj 161123155 H6 r 79416787 ULR ebJnUiTnYgP 31638847 vbusYccDz FPEsDy srjiHhzs fcP *MQ FskP cytKrr KAy soVdG 6752-17-39 AFn eZ yvgu +78789 381595527
vnfi FC 7617 3455 Q 5 C P pVQSdHYUuN +97317.36 cUds f 94779484 HIZXT tAGRyJwiZokJfo 779586649 X6 M 59613139 vWuQf fjykoJF 57762176 IwjeG CSMeynturIUEzk BvJ *oi gCtr GxqzZg REI ZILUr 1916-88-42 Rwo TA jhWg +47967 793474171
Tnkp ZE 4697 r 4 j y IKGbYuA +28363.78 BhfJ s 39813118 CMEBGxJuZ ExCUxUn- krzx MfsbDp 616926757 u8 f 59891125 nGFe iVWItm vBXF DtbnH 51759434 WuzSdMPRk zkjFKrZ- sgeH WuQGnE epp *em oXVU cNCJfh seu xbIxH 6374-73-93 Tzm VZ DbBk +83234 666885577
*******************************************************
This message contains information that is confidential
and proprietary to FedEx Freight or its affiliates.
It is intended only for the recipient named and for
the express purpose(s) described therein.
Any other use is prohibited.
*******************************************************
6. popping, shifting or splicing an array??? - Perl
7. Using $# in a splice with split
Hi Perl buddies,
Can I do something like this:
my $line = 'One Two Three Four Five Six';
my( $first, $last ) = (split(' ', $line))[0,$#(split(' ', $line))];
This does not work. What I want to do is to find the index of the last
element of a list created by split, and use it in a slice on the same
line. Wow, that sounds garbled when I re-read it. With the above
example, I want the two variables to contain the following:
$first = 'One';
$last = 'Six';
I realize I can do this in two steps:
my $line = 'One Two Three Four Five Six';
my @line = split(' ', $line);
my($first, $last) = @line[0,$#line];
But I was wondering if it can be done on one line.
--Errin
PS ---- oops ... I just remembered negative indexing. This works:
my $line = 'One Two Three Four Five Six';
my( $first, $last ) = (split(' ', $line )[0, -1];
Weeeeeeeeeeeeeeeee!
8. Web data clean up - Tie::File splice question(s) - Perl