ArrayGetIndex - What if there's more than one instance?

Hi there. I have an array with thousands of entries. I need to use the ArrayGetIndex function to check if a value is in the array. Simple. But I also need it to continue and get me the next one, too, if it exists, ie:

If array = 1 , 2, 3, 2 , 3 ,4 ,2 and I want it to return indexes 1,3 and 6 - is there a smart way to do it without having to resort to a god-awful loop, or by creating a duplicate array without the first instance?

Thanks!

Subject: ArrayGetIndex - What if there’s more than one instance?

I know it might be a bit of a re-write, but have you ever used the list data type? Its very useful for this sort of thing.

It works like this:

MyList(“Joe”) = “1234”

MyList(“Fred”) = “5678”

MyList(“Matt”) = “9122”

So to reference it:

If a document has a field called username and Fred is the value, then this would result like so:

Temp = MyList(Doc.username(0))

Temp would be equal to “5678”

Subject: RE: ArrayGetIndex - What if there’s more than one instance?

Thanks, Randy, but what if “Fred” is not unique in the list, will it return an array or just the first element?

Subject: RE: ArrayGetIndex - What if there’s more than one instance?

Matthew, could you elaborate some more on what exactly you have to accomplish? Why would you want to retrieve the same value more than once?

The next instance of the value your looking for will - obviously - be just that, the same value. If you’re drawing additional information from the index number, the data structure is just not right. In this case, a list would be better suited. The tags must be unique, but after all the unique difference between the two occurrences would be what you’re after, so why not use these distinctive attributes as the list tag?

If it was just the fact, that the array is not unique, you could use ArrayUnique to help that before using ArrayGetIndex.

The only other reason I could think about is, if you have to count the number of occurrences of a given value in that array. In this case, you could get the size of the array (Ubound - Lbound + 1), use ArrayReplace to replace all instances of this value with an empty string, run Fulltrim to remove the empty elements and finally get the size of the modified array for comparison.

However, this is all just speculation without knowing what you really have to do.

Subject: RE: ArrayGetIndex - What if there’s more than one instance?

Hi Karkpabst!! The situation is as follows. Our company receive an invoice payment from the bank without any customer data to give us an indication which invoice it relates to. We have 44000+ open invoices of which I have built (dynamic) arrays of the values and invoice numbers. I then need to create another array of the invoices whose value matches the payment value. So, my plan was to search the value array and for each index that matched I could extract the matching invoice from the invoice array.

I realise now I could dump the two arrays and create a List instead, but how do I then build my new array of matching items?

Of course, I could scrap the whole thing and just run a query against the Open Items database for each transaction, but I wanted to avoid doing that and work outside DB2.

Subject: RE: ArrayGetIndex - What if there’s more than one instance?

If you have a view that’s sorted by the value you want to search for, it’s quite efficient to search the view for matching documents. While you have the view open in your program, you can find what you need perhaps more efficiently than loading all the data from all the documents, because you don’t have to touch every document – a real performance killer.

If the number of transactions you’re processing at any particular time is a significant fraction of the documents in the view, and you’re modifying or deleting the invoice documents when you find a match, then you might find that you’re spending a significant amount of time updating the view index after processing each entry. In that case, it might make sense to load information from all the documents into memory, though efficiency might also be obtained by taking your input data in sorted order.

(I’m assuming you might have several transactions with the same amount, and several invoices with a matching amount, and you only want to process every invoice once. If the incoming transactions are sorted, then you can process the first entry by looking up all matching view entries and matching the transaction to the first view entry in that amount, then for subsequent entries, if the amount is the same, match it to the next view entry in your collection instead of doing another lookup. That way, you can set the view index not to auto-update, since you know you’ll never look up the same key twice in the run so it doesn’t matter that the previous document has been removed from the view).

If you do decide to load all your document data into memory, it’s also possible to use a more complex data structure. Arrays and lists are only the beginning of what it’s possible to do. Define your own data structures and record all the relevant information – use an array of structures or of class objects, or a sorted linked list or b-tree (publicly available algorithms, go search, or there’s a predefined class in the Domino Design Library Examples). You might use a List datatype whose elements are objects of a collection class type, so that each list key could point to multiple elements.

Subject: RE: ArrayGetIndex - What if there’s more than one instance?

Hi Matthew,

As Harkpabst pointed out, you could build a “compound key” for your list and then eah list member need only contain a scalar value rather than a vector. So when building up your list, you could do somthing like:

Dim view as NotesView

Dim doc as NotesDocument

Dim strKey as String

Dim listLookup List as NotesDocument

'Get reference to the view you are using for lookup and then…

Set doc = view.GetFirstDocument

Do While Not doc Is Nothing

'Assuming all docs have valid values (or conversely, do a check first), …

strKey = doc.GetItemValue(“InvoiceNumber”)(0) & “_” & doc.GetItemValue(“InvoiceTotal”)(0)

Set listLookup(strKey) = doc

Set doc = view.GetNextDocument(doc)

Loop

Now, when trying to search for the matching invoice, you need only supply the invoice number and total as elements to the key in order to see if you found a match. For example, assuming that you are processing text file from which you read the invoice number and total into variables:

strKey = strInvoice & “_” & strTotal

If IsMember(listLookup(strKey)) Then

Set doc = listLookup(strKey)

Call ProcessPament(doc) 'call some custom function on this document

Else

'Not found… Log it?

End If

Now if I have misunderstood what information you have available to you from the bank, i.e. they don’t even supply you the invoice number, you can still use a list but one whose key is just the value and whose elements are NotesDocumentCollections (one way of storing vector data into a list item) but you have a bigger issue to deal with than that, I think.

If “Fred” and “Barney” both owe $100.00 whose account is creditred with Fred’s payment? Does Fred end up paying Barney’s debt?

If Fred makes a partial payment of $80.00, will his account be credited or because there was no match for an $80.00 invoice total, his payment is not processed?