kdb+: Remove elements from a list based on a condition - list

I have a list as below and want to drop dates that are in the past, or the days that are less than today. Do I need an if statement or is there some q like way to do it?
q)d
1970.03.16 1980.03.17 1990.03.19 2000.03.13 2010.03.15
q)type d
14h

You can skip the function all together and do this inline.
Find indices in your list where the dates are greater than today (d>.z.D), then use that list to extract items from your list (d where d>.z.D)
q)d:1970.03.16 1980.03.17 1990.03.19 2020.03.13 2017.09.15
q)d>.z.D
00011b
q)d where d>.z.D
2020.03.13 2017.09.15

I believe I got it:
q)today:`date$.z.z
q)func:{[lst] lst where today<lst}
q)d
1970.03.16 1980.03.17 1990.03.19 2020.03.13 2017.09.15
q)func d
2020.03.13 2017.09.15

Related

Check an Array for latest timestamp

[["a","some_variable_data","01.02.2021"]
["a","some_variable_data","01.03.2021"]
["a","some_variable_data","01.04.2021"]
["a","some_variable_data","11.02.2021"]
["b","some_variable_data","01.02.2020"]
["b","some_variable_data","01.03.2020"]
["b","some_variable_data","01.04.2020"]
["b","some_variable_data","11.02.2020"]]
i have to check the latest timestamp for each first array field and add this to the rows. so the result should look like:
[["a","some_variable_data","01.02.2021"]
["a","some_variable_data","01.03.2021"]
["a","some_variable_data","01.04.2021","latest"]
["a","some_variable_data","11.02.2021"]
["b","some_variable_data","01.02.2020"]
["b","some_variable_data","01.03.2020"]
["b","some_variable_data","01.04.2020","latest"]
["b","some_variable_data","11.02.2020"]]
i need some help/hint how to realize this. can anybody help me? i have to use python 2.7
I'm not sure if sorted([ that array ]) works, but you can try that.
Lets say: array = [ that bigger array you shared ].
We know the location of the dates: the 3rd element (index 2). It's also sorted on the first element of the list: "a" or "b"
A possible option is to split the array into two arrays: one starting with "a" and one with "b".
Next, you can sort on the array_a[2] element in the list. Depending on the date and month, you can see if it was before, or after.
At the end, you simply merge the big arrays together:
print([1,2,3]+[4,5,6]) # [1,2,3,4,5,6]
def latest(n):
n = list(filter(None, n)) #delete_empty
n.sort(key = lambda date: datetime.strptime(date, '%d.%m.%Y')) #sort date
n=n[::-1] #reverse list
#print(n)
latest=""
for lp in n:
latest=lp
break
return latest
found a way:
build list for each first key and sort them as datetime, then pick latest and rebuild the initial list

How to select element from tuple by index in list?

I want to select elements from a list, [[1,2],[3,4],[5,6]] once the first, than the second, than again the first and so on.
I figured that i could use zip to add a counter in front of the pairs and use modulo to select the part, and now my list looks like this:
let a = [(0,[1,2]),(1,[3,4]),(2,[5,6]),(3,[7,8]),(4,[9,10])]
but how can I now select the elements?
the pseudocode would be
for each tuple in list:
first part of tuple is the selector, second part is the pair
if selector mod 2 : choose pair[0] else choose pair[1]
the output for the list a should be: 1,4,5,7,9
Perhaps:
> zipWith (!!) [[1,2],[3,4],[5,6],[7,8],[9,10]] (cycle [0,1])
[1,4,5,8,9]
If you know you're working with lists of length two inside, you should probably be using pairs instead.
> zipWith ($) (cycle [fst, snd]) [(1,2),(3,4),(5,6),(7,8),(9,10)]
[1,4,5,8,9]
I like #DanielWagner answer a lot. The first is so simple and effective. His second is a just a little harder to understand but simple, too. When theories are simple, it increases their veracity. Here is my sorry solution but it does use your structure. (Association lists are tuples. It was suggested you use tuples but for this, what you have and probably need is okay.)
a = [(0,[1,2]),(1,[3,4]),(2,[5,6]),(3,[7,8]),(4,[9,10])]
[if even i then x else y | (i,(x:y:z)) <- a]
[1,4,5,8,9]

Return all elements followed by an equal element using list comprehensions

So I'm new to Erlang and still on the learning curve, one question asked was to return all elements in a list followed by an equal element, to which I could to.
For example...
in_pair_lc([a,a,a,2,b,a,r,r,2,2,b,a]) -> [a,a,r,2]
I was then asked to do the same using a list comprehension, and I hit my mental block.
My unsuccessful attempt was this:
in_pair_lc([]) -> [];
in_pair_lc([H|T]) ->
[X || X ,_ [H|T], X=lists:nth(X+1, [H|T]).
Although with no look ahead in list comp it doesn't work.
Thanks for any help in advance.
One way to do this with a list comprehension is to create two lists from the input list:
one containing all elements except the very first element
one containing all elements except the very last element
By zipping these two lists together, we get a list of tuples where each tuple consists of adjacent elements from the input list. We can then use a list comprehension to take only those tuples whose elements match:
in_pair_lc([_|T]=L) ->
[_|T2] = lists:reverse(L),
[H || {H,H} <- lists:zip(lists:reverse(T2),T)].
EDIT: based on the discussion in the comments, with Erlang/OTP version 17.0 or newer, the two list reversals can be replaced with lists:droplast/1:
in_pair_lc([_|T]=L) ->
[H || {H,H} <- lists:zip(lists:droplast(L), T)].
The first example will work on both older and newer versions of Erlang/OTP.
I'm not convinced the problem is really about list comprehensions. The core of the problem is zipping lists and then using a trivial "filter" expression in the list comprehension.
If you want to stick to basic, long existing, erlang list functions (sublist, nthtail) you could go with the following:
X = [a,a,a,2,b,a,r,r,2,2,b,a].
[A || {A,A} <- lists:zip(lists:sublist(X, length(X)-1), lists:nthtail(1, X))].

Removing the first instance of x from a list

I am new to Haskell and have been trying to pick up the basics.
Assume I have the following list y:
3:3:2:1:9:7:3:[]
I am trying to find a way to delete the first occurrence of 3 in list y. Is this possible using simple list comprehension?
What I tried (this method deletes all instances from a list):
deleteFirst _ [] = []
deleteFirst a (b:bc) | a == b = deleteFirst a bc
| otherwise = b : deleteFirst a bc
No, it's not possible using a list comprehension. In a list comprehension you make a decision which element to keep based on that element only. In your example, you want to treat the first 3 you encounter differently than other 3s (because you only want to remove the first one), so the decision does not depend on the element alone. So a list comprehension won't work.
Your attempt using a recursive function is already pretty close, except that, as you said, it removes all instances. Why does it remove all instances? Because after you removed the first one, you call deleteFirst again on the rest of the list, which will remove the next instance and so on. To fix this, just do not call deleteFirst again after removing the first instance. So just use bc instead of deleteFirst a bc in that case.
as other already mentioned list comprehension is not an appropriate solution to this task (difficult to terminate the execution at one step).
You've almost written the correct solution, just in the case of equality with the matched value you had to terminate the computation by returning the rest of list without the matched element:
deleteFirst _ [] = []
deleteFirst a (b:bc) | a == b = bc
| otherwise = b : deleteFirst a bc
> print $ deleteFirst 3 (3:3:2:1:9:7:3:[])
> [3,2,1,9,7,3]
I don’t believe it is possible to do this with list comprehension (at least not in in any idiomatic way).
Your deleteFirst works almost. All you need to change to fix is is to stop deleting after the first match, i.e. replace deleteFirst a bc in the first clause by bc.
sepp2k's remarks about list comprehensions are an important thing to understand; list operations like map, filter, foldr and so on treat all list items uniformly, and the important thing to understand about them is what information is available at each step, and how each step's result is combined with those of other steps.
But the aspect I want to stress is that I think you should really be trying to solve these problems in terms of library functions. Adapting the solution from this older answer of mine to your problem:
deleteFirst x xs = beforeX ++ afterX
-- Split the list into two pieces:
-- * prefix = all items before first x
-- * suffix = all items after first x
where (beforeX, xAndLater) = break (/=x) xs
afterX = case xAndLater of
[] -> []
(_:xs) -> xs
The trick is that break already has the "up to first hit" behavior built in it. As a further exercise, you can try writing your own version of break; it's always instructive to learn how to write these small, generic and reusable functions.

Prolog list adding

--the question has been edited--
Using this data, I need to create a list:
team(milan,1).
team(napoli,2).
team(lazio,3).
team(roma,4).
team(inter,4).
team(juventus,5).
So, given a query like:
check([milan,lazio,roma,inter]).
make a new list with their respective team number.
X=[1,3,4,4]
What I'm trying to do is creating a list, adding elements one at a time.
check([H|T]) :-
team(H,R),
append([R],_, X),
check(T).
Could someone help me complete this?
You need to find all the team numbers for which the name of the team is a member of the list of team names that you are interested in:
?- findall(Number, (
team(Name, Number),
member(Name, [milan, lazio, roma, inter])), Numbers).
Numbers = [1, 3, 4, 4].
To return the numbers in a given order, just apply member/2 before team/2, in this case member/2 generates names (in the given order), and team/2 maps them to numbers:
?- findall(Number, (
member(Name, [lazio, milan, inter]),
team(Name, Number)), Numbers).
Numbers = [3, 1, 4].
A lot of time since I used Prolog but an answer -more or less- would look like:
check([]) :- true.
check([X]) :- team(X,_).
check([X,Y]) :- team(X,N), team(Y,M), N < M.
check([X,Y|T]) :- check(X,Y), check([Y|T]).
See this question for a very similar problem.
From what you say you might be better off making a list and then sorting it. That way you'd know the list is in order. Of course it's tricky in that you are sorting on the team ranks, not the alphabetic order of their names.
But the question you asked is how to check the list is in sorted order, so let's do it.
check([ ]). % just in case an empty list is supplied
check([_]). % singleton lists are also in sort order
check([H1,H2|T]) :-
team(H1,R1),
team(H2,R2),
R1 <= R2,
check([H2|T]).
Note that the recursion reduces lists with at least two items by one, so the usual termination case will be getting down to a list of length one. That's the only tricky part of this check.
Added in response to comment/question edit:
Sure, it's good to learn a variety of simple "design patterns" when you are getting going with Prolog. In this case we want to "apply" a function to each item of a list and build a new list that contains the images.
mapTeamRank([ ],[ ]). % image of empty list is empty
mapTeamRank([H|T],[R|S]) :-
team(H,R),
mapTeamRank(T,S).
So now you have a predicate that will turn a list of teams LT into the corresponding list of ranks LR, and you can "check" this for sorted order by calling msort(LR,LR):
check(LT) :-
mapTeamRank(LT,LR),
msort(LR,LR).