How to iterate through the list in aerospike using golang? - go

I am using the list data type (http://www.aerospike.com/docs/guide/cdt-list.html
) in aerospike using a golang client. I can use the ListInsertOp (https://godoc.org/github.com/aerospike/aerospike-client-go#ListInsertOp) to insert values in the list of a given entry.
However, I want to update/delete a given list value using the ListSetOp (https://godoc.org/github.com/aerospike/aerospike-client-go#ListSetOp) or the ListRemoveOp (https://godoc.org/github.com/aerospike/aerospike-client-go#ListRemoveOp)
In order to do this, I need an index. How can I get this index ? Is there a way I can iterate through all the list values and get the index and then perform the update or delete operation ?

Assuming that you have the list called List.
Let us say you want to replace element called value with newItem
You can do that like:
...
for index, item := range List {
if item == value {
List[index] = newItem
}
}
...
In the above snippet, index is the index at which element item is present. By this way you can also replace element present on the particular index in the list with value.
Sample example in playground: https://play.golang.org/p/qOmsY9fbL2

As usual, items in the list are indexed by their integer position starting from zero.
Aerospike also supports negative indexing to start backwards from end of list.
Lists documentation in the Aerospike:
Elements are ordered by integer position.
Lists documentation in the Aerospike's Node.js client:
List operations support negative indexing. If the index is negative, the resolved index starts backwards from end of list.
Index/Range examples:
Index 0: First item in list.
Index 4: Fifth item in list.
Index -1: Last item in list.
Index -3: Third to last item in list.
Also mentioned in Go client source.
list := []string{“a”, “b”, “c”, “d”, “e”}
bin := aerospike.NewBin("listbin", list)
err := client.PutBins(nil, key, bin)
// to replace “d”:
op := aerospike.ListSetOp(bin.Name, 3, "replaced")
_, err = client.Operate(nil, key, op)

Related

Better way to deal with nil slice indexes

I have started a project for creating reports by utilizing excel data and the various Go excel libraries (excelize, tealeg's xlsx)
One of the biggest frustrations I have found is working with slices which have some nil indexes depending on the source of data (blank rows in the input data transfer as "nil" slice indexes when I use the xlsx library to pull data)
These nil slice index throw an "index out of range" obviously if I ever try and utilize them in one of my many for loops - which leads me to the painstaking task of ensuring each time I want to work with a slice index that is isn't actually nil by using len() and cap to death()(excerpt of code below to illustrate)
//example code excerpt
for rowNumber, cellStringSlice := range inputSlice {
for rowColumn, cellString := range cellStringSlice {
//loop var declaration
rowColumnHeading := 2
rowNumberInc := rowNumber + 1
rowNumberDec := rowNumber - 1
if rowNumber > 0 {
if len(inputSlice[rowNumber]) != 0 { //len check to stop index out of range issue with slice
previousColACellValue = inputSlice[rowNumber][rowColumn]
continue
}
if len(inputSlice[rowNumber+1]) != 0 { //len check to stop index out of range issue with slice
nextColACellValue = inputSlice[rowNumber+1][rowColumn]
continue
}
}
}
I should specify that in this 2D slice I am using:
inputSlice[rowNumber][rowColumn]
the proximal slice (rowNumber) is never nil (there is always a row) however the second distal slice it indexes (rowColumn) Can be nil on some instances - which is why in this scenario my overall loop always enters the second inner loop even when it is iterating though a row with no column data (i.e inputSlice[rowNumber][rowColumn] = nil) and brings a frequent need for me to handle index out of range issues
I can't just remove all the nil indexes and shift everything up, as these are representing "blank rows" in the final excel doc I output these rows to.
So my question is, are there any useful go functions or libraries which take care of nil indexes by swapping all nils for "" in slices and 2d/3d slices of type string? Or is it a task for the programmer to always "sanitise" his slices by removing these nils or check for them each time they ever want to access an element?
I appreciate I could write a for loop myself to swap all these nils for a "", but writing a function to do this each time I work with slices of strings containing/possibly containing nil's would seem a little bizarre to me
Your outer loop is on inputSlice, so inputSlice[rowNumber] is always valid, and since the inner loop is on that row, it is never zero. Thus the first check is unnecessary. If you have a nil or empty slice for inputSlice[rowNumber], the inner for loop will not even be entered.
The second check is necessary, but wrong:
if len(inputSlice[rowNumber+1]) != 0 {
If rowNumber is the last row, then inputSlice[rowNumber+1] is not valid as no such row exists. You have to check:
if rowNumber<len(inputSlice) {
...
}

Why do I get 6 entries in an array created from a map with only 3 entities?

I have a seemingly simple issue with my understanding of map types in Go. If I create a simple map such as
var thisMap = map[string]string {
"8f14e45fceea167a5a36dedd4bea2543": "Charming",
"1679091c5a880faf6fb5e6087eb1b2dc": "Citi",
"e4da3b7fbbce2345d7772b0674a318d5": "Chase",
}
Populate the keys into an array
keys := make([]string, len(supportedCards))
for k := range supportedCards {
keys = append(keys, k)
}
Then try to join these keys into a comma separated value that I can append to any string
fmt.Println(strings.Join(keys,","))
I expect the result to be
8f14e45fceea167a5a36dedd4bea2543,1679091c5a880faf6fb5e6087eb1b2dc,e4da3b7fbbce2345d7772b0674a318d5
But what I really see is
,,,8f14e45fceea167a5a36dedd4bea2543,1679091c5a880faf6fb5e6087eb1b2dc,e4da3b7fbbce2345d7772b0674a318d5
Why does iterating through the map create 6 entries instead of just 3?
https://play.golang.org/p/Ou67K1Kfvsf
With
keys := make([]string, len(supportedCards))
you create a []string with three empty elements. You can assign them using their indicies.
When you append it later, new entries are added at the end, producing your result with a length of 6, where the first three are empty.
In addition to #xarantolus's answer, instead of using indices you can keep your for-range loop unchanged by:
keys := make([]string, 0, len(supportedCards))
The third argument is capacity of the slide. Ref: https://tour.golang.org/moretypes/13

Linq statement involving index based update of value not working

In my C# winforms project, I wanted to update a specific index based position in a collection (named List l1 here).
I tried below code:
l1.Where((s, i1) => i1 == intvalue).Select(s => { if (s > 0) s = -1; return s; };
I wanted to set value at invalue index to -1 in the list l1, but when I do so with above statement the value in l1 is not changed. Please help! I am new to Linq and have searched the topic 'index based change of value in a collection' everywhere, but can't resolve my problem as it involves BigInteger type and I have so many elements in the list that their total count passes the allowed max value for int type in c#. So when I type l1[intvalue] it says can't convert BigInteger to int for index position.
Thanks
LINQ is Language INtegrated Queries. It's purpose is querying data. If you want to modify list item:
if (l1[intvalue] > 0)
l1[intvalue] = -1;
Also I'd like to explain why your query is not changing list.
On first step you are selecting list items by some condition. Very strange condition by the way. If you want to select item by index, there is operator ElementAt.
Then you are doing projection. I.e. you are calling anonymous method which accepts each selected item and produce some result. Each item passed to that method as s argument. And when you are assigning -1 to s you are actually assigning value to method argument. That does not affect items in the list. Even if your list will contain items of reference type instead of integers, assigning value to method argument will just change where argument variable points. It will not change references in original list. Though you still can modify items of reference type. But such side-effects in projection methods are not good practice.

Data structure to check if number of elements is equal in O(1) time?

What is the best data structure to check if the number of elements of different types of objects is the same?
For example, if I have
2 a's
3 b's
3 c's
The number of elements of the different types of objects is not the same.
If I have
2 a's
2 b's
2 c's
then this is the same.
What is the best data structure that allows you do this in O(1) time and how would you implement it?
One method is to use two dictionaries to be able to do it in O(1) dynamically.
The first maps each type to a count, {a:2,b:3,c:3}. The second maps each count to a set of types with that count. {2:{a},3:{b,c}}. If the size of the second dictionary is less than 2 (0 or 1) then clearly all types have the same count as if that was not the case then there would be at least two key-item pairs in that dictionary, presuming that the dictionary is updated when the counts change.
Adding a type just means adding it to each dictionary.
Removing a type just means removing it from each dictionary.
Updating a type requires first updating the second dictionary by removing the previous count (obtained from the first dictionary) and adding the current count, after which the first dictionary is updated.
Dictionary<Type, int> typeCounts = new Dictionary<Type, int>();
// read and store type counts
Type type = typeof(A);
if (typeCounts.Contains(type))
{
typeCounts[type]++;
}
else
{
typeCounts.Add(type, 1);
}
// populate type counts by type and finally:
if (typeCounts[typeA] == typeCounts[typeB])
{
// so on
}

Data structure optimized for adding items (at end of list), iterating, and removing items

I need a data structure which will support the following operations in a performant manner:
Adding an item to the end of the list
Iterating through the list in the order the items were added to it (random access is not important)
Removing an item from the list
What type of data structure should I use? (I will post what I am currently thinking of as an answer below.)
You should use a linked list. Adding an item to the end of the list is O(1). Iterating is easy, and you can remove an item from any known position in the list in O(1) as well.
It sounds like a linked list, however there's a catch you need to consider. When you say "removing an item from the list", it depends on whether you have the "complete item" to remove, or just its value.
I will clarify: let's say your values are strings. You can construct a class/struct containing a string and two linking pointers (forwards and backwards). When given such a class, it's very easy to remove it from the list in O(1). In pseudo code, removing item c looks like this (please disregard validation tests):
c.backwards = c.forwards
if c.backwards = null: head = c.forwards
if c.forwards = null: tail = c.backwards
delete c
However, if you wish to delete the item containing the string "hello", that would take O(n) because you would need to iterate through the list.
If that's the case I would recommend using a combination of a linked list and and hash table for O(1) lookup. Inserting to the end of the list (pseudo code):
new_item = new Item(value = some_string, backwards = tail, forwards = null)
tail.forwards = new_item
tail = new_item
hash.add(key = some_string, value = new_item)
Scanning through the list is just scanning through the linked list, no problems:
i = head
while i != null:
... do something with i.value ...
i = i.forwards
Removing an item from the list by value (pseudo code, no validation testing):
item_to_remove = hash.find_by_key(some_string)
if (item_to_remove != null):
hash.delete_key(some_string)
item_to_remove.backwards = item_to_remove.forwards
if item_to_remove.forwards = null: tail = item_to_remove.backwards
if item_to_remove.backwards = null: head = item_to_remove.forwards
delete item_to_remove
I am thinking of using a simple list of the items. When a new item is added I will just add it to the end of the list. To remove an item, I won't actually remove it from the list, I will just mark it as deleted, and skip over it when iterating through the items.
I will keep track of the number of deleted items in the list, and when more than half of the items are deleted, I will create a new list without the deleted items.
Circular & Doubly-Linked List. It satisfies all 3 requirements:
Adding an item to the end of the list: O(1). By add to Head->prev. It supports Iterating through the list in the same order in which they were added. You can remove any element.
Assuming Java (other languages have similar structures, but I found the JavaDocs first):
ArrayList if you have the index of the item you want to delete
LinkedHashMap if you only have the item and not its position

Resources