Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

How do I insert an element into an arbitrary (in range) array index?

by Anonymous Monk
on Sep 03, 2000 at 23:55 UTC ( #30939=categorized question: print w/replies, xml ) Need Help??
Contributed by Anonymous Monk on Sep 03, 2000 at 23:55 UTC
Q&A  > arrays

Answer: How do I insert an element into an arbitrary (in range) array index?
contributed by Russ

Use splice with 0 for the length argument.

my @R = (1,2,3,4,5,6,7,8,9); splice @R, 1, 0, 'Test'; print "@R\n";
prints: 1 Test 2 3 4 5 6 7 8 9
Answer: How do I insert an element into an arbitrary (in range) array index?
contributed by jreades

Algorithms with Perl (call it the Wolf book) covers just this issue in one of the early chapters

Basically, you have two choices: an array or a linked list.

The choice between these two will depend on, primarily, the size of the list.

Splice(): As lhoward indicated, inserting a value at an aribtrary index using splice is expensive.

The time for each splice() increases at a constant rate as your list grows in size. With splice(), although from the user end it looks like you just inserted something, to memory you were creating and manipulating multiple arrays (basically, a one or more copies of your original array) in memory.

This may not be a problem if your array is 10, 20, or even 100 items, but if it's 10,000 or 100,000 you're going to see a real performance hit. This brings us to...

Linked Lists: perhaps the easiest (and probably least accurate) way to describe it is to say that linked lists are array-like.

The basic principle is that you have a value (call it 'x') and a pointer (reference, call it 'a') to the next item (call it 'y') in the linked list (assuming a simple linked list).

So a(x) -> b(y) -> c(z) and so on...

Suddenly, we've radically altered the tradeoffs... To add a value q between x and y I just need to change the pointers as follows:

a(x) -> e(q) -> b(y) -> c(z) and so on...

The cost of inserting values at arbitrary locations is reduced to, I believe, O(1) -- I can insert anywhere in the list just by rearranging the pointers and that is essentially a constant time operation regardless of how big my list is...

Of course, now I might have some trouble *finding* the element, but that's another question entirely...

Answer: How do I insert an element into an arbitrary (in range) array index?
contributed by lhoward

By insert I assume you mean "put between 2 current array elements, shifting down the later ones to make room".

The unfortunate answer is that you can't do this efficiently using native perl arrays. The code to do it isn't long or complex, but as a consequence of the design of perl's arrays (which makes them so efficient at so many other operations) sacrifices had to be made. One of those is that inserting in the middle of an array is "slow" — the time it takes to do it depends on how many elements are already in the array. (In big-O notation, the operation is said to be O(n).).

my @array = qw(3 1 4 1 5 9 2 6 5 4); my $offset = 5; my $value = 'abc'; print "before: @array\n"; splice @array, $offset, 0, $value; print " after: @array\n";
Answer: How do I insert an element into an arbitrary (in range) array index?
contributed by Jorge_de_Burgos

#!/usr/bin/perl -w use warnings; use strict; use 5.10.0; my @in_array = qw(A B C E F G); my @out_array; my $insert = 'D'; push @out_array, @in_array[0..2], $insert, @in_array[3..5]; say join (', ', @in_array); say join (', ', @out_array); exit;
I think this approach is the most human-readable. By the way, it doesn't use splice with its performance issues.
Answer: How do I insert an element into an arbitrary (in range) array index?
contributed by Denis.Beurive

Hello! You can use this function :

sub arrayInsertAfterPosition { my ($inArray, $inPosition, $inElement) = @_; my @res = (); my @after = (); my $arrayLength = int @{$inArray}; if ($inPosition < 0) { @after = @{$inArray}; } else { if ($inPosition >= $arrayLength) { $inPosition = $arrayLen +gth - 1; } if ($inPosition < $arrayLength - 1) { @after = @{$inArray}[($ +inPosition+1)..($arrayLength-1)]; } } push (@res, @{$inArray}[0..$inPosition], $inElement, @after); return @res; } my @tab = qw(A B C D E); my @res = (); @res = arrayInsertAfterPosition (\@tab, -1, 'Test'); print join(', ', @res) . "\n"; @res = arrayInsertAfterPosition (\@tab, 0, 'Test'); print join(', ', @res) . "\n"; @res = arrayInsertAfterPosition (\@tab, 1, 'Test'); print join(', ', @res) . "\n"; @res = arrayInsertAfterPosition (\@tab, 2, 'Test'); print join(', ', @res) . "\n"; @res = arrayInsertAfterPosition (\@tab, 3, 'Test'); print join(', ', @res) . "\n"; @res = arrayInsertAfterPosition (\@tab, 4, 'Test'); print join(', ', @res) . "\n"; @res = arrayInsertAfterPosition (\@tab, 5, 'Test'); print join(', ', @res) . "\n";

The result is :

Test, A, B, C, D, E A, Test, B, C, D, E A, B, Test, C, D, E A, B, C, Test, D, E A, B, C, D, Test, E A, B, C, D, E, Test A, B, C, D, E, Test

Please (register and) log in if you wish to add an answer

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    [Corion]: ambrus: Hmmm. It makes sense that AnyEvent would implement the push_write itself, but I think I don't have a good idea of where the boundary between AnyEvent and the underlying event system lies... Implementing the timer should give me a better idea
    [ambrus]: Corion: push_write is in the higher level abstraction of AnyEvent::Handle, not in the watcher
    [Corion]: ambrus: Hmm - rereading Prima::File, that merrily coincides with what Prima does - it tells you "you can read", and you're supposed to read from the fh yourself. I thought it called you with the data already read, which would've been harder to integrate
    [ambrus]: you just need an io watcher, created by &AnyEvent::Impl:: Whatever::io(...)
    [Corion]: So after talking it through with you even while I'm still not entirely clear on where AE ends and my implementation begins, I think I understand that I only need to implement some smaller parts for each functionality I want to support.
    [Corion]: Yeah... and you might even be able to mix and match additional functionality if you have additional async suppliers, like from a separate thread
    [ambrus]: You hvae to be careful with the timer, because apparently Prima::Timer insists on being periodic, wheras AnyEvent::Impl:: Whatever::timer should give a one-shot timer watcher

    How do I use this? | Other CB clients
    Other Users?
    Others musing on the Monastery: (6)
    As of 2016-12-08 12:23 GMT
    Find Nodes?
      Voting Booth?
      On a regular basis, I'm most likely to spy upon:

      Results (141 votes). Check out past polls.