LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
Darin.K

Negative Values in Index Array or Array Subset

Status: New

There are many times when I need to grab the last element or last n elements of an array.   This usually involves a call to Array Size and then a subtraction, costing me time and block diagram clutter.  Array reversal is essentially free, but again costs clutter and clicks.  For common array types I have personal VIs to do the job, but that is just a band-aid with the proliferation of data types that I use.  My idea would be to treat negative values input to the index array or array subset VIs (for example) as counting from the end of the array.  The last value would have index -1 and so on.  To get the last n values I would put -n into the Array subset VI and that's it.   For expanding the Array Index VI, my preference would be that it counts down (-2,-3,-4,...).

 

 

 NegativeArrayIndex.png

10 Comments
Yamaeda
Proven Zealot

I like the idea, although i'd break some of my own code since i use the -1 to get an empty array at times. 🙂 You could make your own index array which has a reverse array if index <0. A bit cumbersome as you'd need to make a polymorphic one for all existing arrays ... but still.

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
AristosQueue (NI)
NI Employee (retired)

Have thought about this for a while...

 

Changing the existing Index Array function seems fraught with peril for existing code and doesn't seem to provide any sort of upgrade path. And I see the flaw in my suggestion of "just use Reverse Array" -- although that suggestion does work (and works without creating a copy of the array for those who don't know that), it doesn't allow for a programmatic computation that could give either a positive or negative value, which could be useful for things such as a circular buffer.

 

How about this:

Introducing a SECOND primitive that is "Index Array From Both Ends" or something like that does seem like a viable approach. Do you users think that would be too confusing for new users seeing both in the palettes? If we did this, what behavior would you expect for an unwired terminal? In the existing Index Array primitive, an unwired terminal is either index 0 (if it is the first terminal) or the previous index +1. Would it still be "previous +1" or would it be "previous +1 or -1 depending upon the sign of the previous"? Should the new primitive continue to return the last index if given an out of range value or would you introduce error out?

Darin.K
Trusted Enthusiast

Ah, baby steps.  Reverse Array was never really the answer.  It seems like a good idea, but one look at an actual implementation can be eye opening.  On top of that, the nice properties of Reverse Array are easily lost when you have to do it conditionally.  Put it inside a Case Structure and the compiler starts throwing copies around the BD.  (Maybe better in newer versions).  The 'better' workaround is a set of polymorphic VIs and the realization that a small number of datatypes go a long way.  XNodes are also feasible, but I would like to seem them distributable as packed project libraries.  You know, a single top level VI that gets dropped and a set of subVIs that aren't really useful outside the XNode.

 

While alternate indexing is on your mind, it is time to relax, forget about C++ and pointer math, clear your mind and only consider by value array representations.  Now ask yourself, why start from 0?  I think the FIRST element should be 1, beautiful symmetry with the last element being -1.  0 is a truly special, singular, special value for null or not found.  So many +1 and -1 nodes could be retired.  And everybody does the same comparison for not found (=0?) instead of (=-1? or <0?).

 

Enough pipe dreaming, as to the new primitive I would probably suggest a new style to handle the autoincrement/decrement.  I would allow the pulldown to create new groups or blocks of elements.  Only one index could be wired inside a block, the rest automatically increment or decrement depending on whether it is above or below the wired index.  I would allow multiple blocks to save space.  Pulling on the top or bottom of the node adds a new group, each group could have a divider which would add elements when pulled (pull down to add to the end of the upper group, pull up to add to the top of the group below) and remove elements when shift-pulled.  Not that this in any way, shape or form resembles an XNode of mine. 

AristosQueue (NI)
NI Employee (retired)

> Not that this in any way, shape or form resembles an XNode of mine. 

 

Have you posted it anywhere that others could evaluate it?

 

Regarding your tangent:

> I think the FIRST element should be 1,

 

I've worked in unit-indexed languages. I hope never again. I too thought it would be better in theory. The experience is miserable. You think +1 and -1 operations get retired. Instead, they move around and they add a few new ones.

 

And that's all I'll say on the topic since it really isn't ever going to happen in LV and I'd like to stay focused on the indexing problem at hand.

Intaris
Proven Zealot

Personally, I'm not sure a new primitive is the answer.  It almost sounds like we need a new datatype "Circular Buffer" which is an array on steroids.  Then you can introduce all kinds of relative operations and having a fixed length array to boot allows for all kinds of optimisations not possible with arrays......

 

But back on planet earth, I think either a second primitive or a right-click option on the index terminal of the array operator would both be workable.  Oh, and if a right.click would be implemented, it MUST be clear visibly which mode is selected!

GregSands
Active Participant

If we did this, what behavior would you expect for an unwired terminal? In the existing Index Array primitive, an unwired terminal is either index 0 (if it is the first terminal) or the previous index +1. Would it still be "previous +1" or would it be "previous +1 or -1 depending upon the sign of the previous"?

 

I'd like both! What about changing the default "box" at the index position to a + or - sign.  By default + is shown, but a right-click option could change that to -, and could be independent of the sign of the wired terminal.

 

Further, could one wire a middle index, and have + on one side, with - on the other?  Might get tricky with multiple wired terminals, but the earliest wiring would take precedence until another index is wired.

 

Should the new primitive continue to return the last index if given an out of range value or would you introduce error out?

 

I can see reasons for either of those (returning the first index for a negative out of range), but also for returning a "default" value (equivalent to the Case default), or even to wrap the index (modulo #elements), which makes it like a circular buffer.

johnsold
Knight of NI

Consider putting an "inversion circle" like the ones used in the Compound Arithmetic and some Boolean functions on the index input. Make it a right-click option. When the inverted mode is present the indexing is from the other end of the array (for that dimension only). 

 

This will allow indexing in either direction to be zero based and will not break legacy code.

 

Invert index.png

Lynn

Darin.K
Trusted Enthusiast

> Consider putting an "inversion circle" like the ones used in the Compound Arithmetic and some Boolean functions on the index input

 

Assuming they do this as well:

 

http://forums.ni.com/t5/LabVIEW-Idea-Exchange/Enlarge-the-Invert-Circles/idi-p/1023748

dnoble79
Member

My suggestion is to add a item to the context menu to select between Absolute and Modulus (or Modulo) Indexing. For example:Array Modulus Indexing.pngThe default is Absolute so existing functionality is unchanged. Modulus Indexing can be selected when needed. This way -1 gives the last element in the array, -2 the second last and so on till the wraps around. The same could be added to other array functions.

These functions would be great for circular buffers too!

 

AristosQueue (NI)
NI Employee (retired)

I uploaded a malleable VI that does this:

The document has been Archived -- no longer available

I've played with this functionality a bit (since I've had malleable VIs longer than most of you). Honestly, the negative indicies just feel error prone. After using this in a couple places, I think I would rather have a function "Reverse Index Array" in the palettes so the last element is index 0. The "off by one" feeling is really hard to think about.

 

This node isn't growable, so it doesn't give the full Index Array experience, but I figured some people in this discussion might want to play with it.