Lotus Notes - #Subset function - get the last element - view

I'm trying to find out how to get the last position from a list obtained from
#Unique ( #DbLookup( "" : "NoCache" ; #DbName ; _view ; field1+field2 ; 2 ));
This gives me a list containing , let say , 5 elements. ( I don't know always how much elements there are in it ).
I just to get the last element ( from last position ) ! Thanks in advance.

Actually the answer is in your question's title itself. You can use the #Subset function to do that. So your code would be:
list := #Unique ( #DbLookup( "" : "NoCache" ; #DbName ; _view ; field1+field2 ; 2 ));
lastElement := #Subset(list; -1);
The help documentation says that: If you specify a negative number, #Subset searches the list from right to left, but the result is ordered as from the beginning of the list.

Related

Access Values of Cell Array deeply nested within Structure Array

I have a nested structure_array/cell_array/structure_array of character values which is the result of a web query which returns a converted JSON object, the needed numeric value(s) of which I can access in loops thus:
for ix = 1 : size( S.orderBook.buckets , 2 )
if ( str2double( S.orderBook.buckets{ ix }.price ) >= str2double( S.orderBook.price ) )
mid_ix = ix ;
break ;
endif
endfor
The above loop gets the index, mid_ix, of the cell in the middle of the region of interest, and
orderbook_begin_ix = mid_ix - 20 ; orderbook_end_ix = mid_ix + 20 ;
jj = 0 ;
for ix = orderbook_begin_ix : orderbook_end_ix
jj = jj + 1 ;
new_orderbook_data( 1 , jj ) = str2double( S.orderBook.buckets{ ix }.longCountPercent ) ;
endfor
this second loop fills the pre-initialised matrix, new_orderbook_data, with the values of interest.
However, I was wondering whether there is a quicker/more elegant way of getting these values? At the moment, as can be seen above, I am having to run a "look up" for loop that encloses an "if statement" to get in the ballpark of the required numeric values, and then run a second for loop in the region of the ballpark to extract these required values.
Note: cross posted at Octave forum
I think I have solved this by using the syntax below:
prices = cellfun( #str2double , { [ S.orderBook.buckets{:} ].price } ) ;
which gives me a matrix "prices" to which I can further apply vectorised code.
Explanation:-
the { : } extracts the prices from the cell array into a comma
separated list,
the enclosing [ ] puts this list into a structure array,
the [ ].price extracts just the prices which are then put back into a
cell array with the outermost enclosing { }
and then the string values are converted to numeric by applying the
cellfun to this prices cell array and
are finally assigned to the "prices" matrix.

prolog replacing elements in list

I need help with understanding how to work with lists like that [a(b,c),a(x,d)]
change(S,K,R) changes first list [a,c,b] with values given in second list [c(a,x),c(b,y)]
?- change([a,c,b],[k(a,x),k(b,y)],R).
R = [x,c,y].
% my program but it works with second list that is of wrong list elements type k(a,x) but like [a,x] and works kinda poorly cause return True instead of R= x,c,y, if i print R value it is [y,c,x|_2826]
i call my code with ?- change([a,c,b],[a,x,b,y],R).
change([],[],[]):-!.
change([],[],R):-write(R),!.
change([H1|T1],[],[H1|R]):-change(T1,[],R),!.
change([H1|T1],[H2,H3|T2],R) :-
( ( H1==H2 , change(T1,T2,[H3|R]) )
; ( H1\==H2, change(T1,[H2,H3|T2],[H1|R]) )
).
Looks like you should use Association lists.
see SWI-Prolog manual
and the online doc

Prolog simple assignment not simple for me

I must say that I don't understand this language at all but I want to learn it by example so please understand me. I have to write out all persons
that have borrowed at least two items (by id and letter of these persons).
Here is simple database :)
person(1,"A").
person(2,"B").
person(3,"C").
person(4,"D").
person(5,"E").
person(6,"F").
borrowed(1001,1).
borrowed(1002,1).
borrowed(2001,1).
borrowed(1004,2).
borrowed(1005,4).
borrowed(2003,4).
borrowed(2005,5).
borrowed(2006,5).
Assuming that your person/2 is defined as person( unique-id , name ) and that your borrowed/2 represents borrowed( id-of-borrowed-item , person-id-of-borrower ), something like this ought to do you:
borrower_by_count( Name , N ) :-
person(Id,Name) , % find the person
findall(X,borrowed(X,Id),Xs) , % find all the items they've borrowed
length(Xs,N). % check the length:
This will work for any value of N. Something like borrower_by_count( Name , 3 ). should return
Name = "A"
and borrower_by_count( Name , 2 ). should return (as you backtrack into it):
Name = "D"
Name = "E'
It also works the other way: borrowed( "A" , N ) should return
N = 3.
And if both arguments are unbound, it should successively enumerate each person and the number of item's they've borrowed.

go imap: bad sequence set value ""

I'm trying to follow the IMAP example but I get this error imap: bad sequence set value "" which corresponds with the line set, _ := imap.NewSeqSet("") from the example. Is it a bug in the lib or a typo in the documentation ?
I'm trying to fetch all the messages so setting the sequence to wildcard ( * ) doesn't seem to work either. I've also tried to read RFC with little success. All I could find about the sequence values is this
seq-number = nz-number / "*"
; message sequence number (COPY, FETCH, STORE
; commands) or unique identifier (UID COPY,
; UID FETCH, UID STORE commands).
; * represents the largest number in use. In
; the case of message sequence numbers, it is
; the number of messages in a non-empty mailbox.
; In the case of unique identifiers, it is the
; unique identifier of the last message in the
; mailbox or, if the mailbox is empty, the
; mailbox's current UIDNEXT value.
; The server should respond with a tagged BAD
; response to a command that uses a message
; sequence number greater than the number of
; messages in the selected mailbox. This
; includes "*" if the selected mailbox is empty.
seq-range = seq-number ":" seq-number
; two seq-number values and all values between
; these two regardless of order.
; Example: 2:4 and 4:2 are equivalent and indicate
; values 2, 3, and 4.
; Example: a unique identifier sequence range of
; 3291:* includes the UID of the last message in
; the mailbox, even if that value is less than 3291.
sequence-set = (seq-number / seq-range) *("," sequence-set)
; set of seq-number values, regardless of order.
; Servers MAY coalesce overlaps and/or execute the
; sequence in any order.
; Example: a message sequence number set of
; 2,4:7,9,12:* for a mailbox with 15 messages is
; equivalent to 2,4,5,6,7,9,12,13,14,15
; Example: a message sequence number set of *:4,5:7
; for a mailbox with 10 messages is equivalent to
; 10,9,8,7,6,5,4,5,6,7 and MAY be reordered and
; overlap coalesced to be 4,5,6,7,8,9,10.
status = "STATUS" SP mailbox SP
"(" status-att *(SP status-att) ")"
Here's the code you're copying from.
// Fetch the headers of the 10 most recent messages
set, _ := imap.NewSeqSet("")
if c.Mailbox.Messages >= 10 {
set.AddRange(c.Mailbox.Messages-9, c.Mailbox.Messages)
} else {
set.Add("1:*")
}
cmd, _ = c.Fetch(set, "RFC822.HEADER")
That code sets a variable to "" but never uses that value. It uses another value, which depends on the state of the c.Mailbox object.
The lesson here is that copying a single line from the documentation isn't enough, you need to look at the surroundings.
It seems there is a typo in the Go doc. set, err := imap.NewSeqSet("1:*") fixes the issue.

Calculate a delta from list

I have this list:
ADD X
ADD Y
REMOVE Z
ADD X
NO ACTION Y
I need of this results:
ADD X
NO ACTION Y
REMOVE Z
The rules to calculate the delta are these:
I have 3 action (ADD, REMOVE, NO ACTION)
ANY ACTION * NO ACTION = NO ACTION
ADD * REMOVE or REMOVE * ADD = NO ACTION
SAME ACTION * SAME ACTION = SAME ACTION
The problem is that I implement this with a functional language (XQuery). I found a logic, based on fn:distinct-values. But the last rule (3) is unsatisfied.
Thanks in advance!!
You didn't mention what XQuery processor you are using, but if it has hashmaps, you can do it this way (tested in MarkLogic Server):
let $seq := ("ADD X", "ADD Y", "REMOVE Z", "ADD X", "NO-ACTION Y")
let $map := map:map()
let $_ :=
for $s in $seq
let $parts := fn:tokenize($s, " ")
let $service := $parts[2]
let $action := $parts[1]
let $current-action := map:get($map, $service)
return
if ("NO-ACTION" = ($action, $current-action)) then
map:put($map, $service, "NO-ACTION") (: rule 1 :)
else if ("REMOVE" = ($action, $current-action)) then
map:put($map, $service, "REMOVE") (: rule 2 :)
else
map:put($map, $service, $action) (: actions are the same -- rule 3 :)
for $service in map:keys($map)
return fn:concat(map:get($map, $service), " ", $service)
Returns
ADD X
REMOVE Z
NO-ACTION Y
Note that I made a simplifying assumption and changed "NO ACTION" to "NO-ACTION" to make the parsing simpler.
Finally I found the way. I hope that this is good.
These are my first experiments with XQuery and I need to remeber what I have under my fingers and what possibilities this language offer.
My problem is data that came in. And I decide to transformate the information in a structure that can I easily manipulate.
A golden brick to solve this is this example about grouping data :
for $d in distinct-values(doc("order.xml")//item/#dept)
let $items := doc("order.xml")//item[#dept = $d]
order by $d
return <department code="{$d}">{
for $i in $items
order by $i/#num
return $i
}</department>
After this I used this algorithm:
0. If the count of action == 1 -> take first action
1. else If exist almost ONE - NO ACTION -> NO ACTION (RULE 1)
2. else If exist ADD and REMOVE in same list -> NO ACTION (RULE 2)
3. else take the first action (equal actions)
For this I borrowed a function from functx library:
declare function local:is-value-in-sequence( $value as xs:anyAtomicType? ,$seq as xs:anyAtomicType* ) as xs:boolean {
$value = $seq
};
Simple but effective.
Thanks a lot for all!

Resources