Scala - merge Lists into one List element-wise - list

I'm trying to merge records stored as List's into one List, where only one column with non-unique values is a List, the rest of the List are single elements.
Below is the example of what I mean by it:
val list1 = List(1, 2, "abcd", 5)
val list2 = List(1, 2, "efgh", 5)
What I need after merging is something like this:
List(1, 2, List("abcd", "efgh"), 5)
I'm very new to Scala, so I'd appreciate your help.

for ((x,y) <- list1.zip(list2)) yield if (x == y) x else List(x,y)
zip combines the two lists and gives you a list of pairs
the for comprehension goes through these pairs. If both are equal it yields only the first element, otherwise a list containing both elements.
Your code might become simpler if you manage to keep your lists homogeneous, i.e. all elements having the same type.

All the lists are of the same length and always the third element is the divergent one
Then use a tuple, it would be better model your data, it would preserve the type information and it would be easier to do the combination.
def merge[A, B, C, D](t1: (A, B, C, D), t2: (A, B, C, D)): Option[(A, B, (C, C), D)] =
t1 match {
case (a, b, c1, d) =>
t2 match {
case (`a`, `b`, c2, `d`) => Some((a, b, (c1, c2), d))
case _ => None // The other elements not where equal.
}
}

Related

Change list of variables according to another list containing the index and atoms in prolog

I have a list of variables E and a list L and I want a predicate that works like this:
E=[A,B,C,D]
L=[(1,b),(3,m)]
solve(E,L).
E=[b,B,m,D]
Basically solve() should run through the list L and change E by using (a,b) to unify the variable at index a with the atom B. Is there any way to do this?
The meaning of the (badly named) solve/2 predicate is something like "for every pair (Index, Element), the Index-th element of the input list is Element". You are likely using a Prolog implementation that already has a predicate called something like nth1/3 which expresses "the Index-th element of List is Element". For example, in SWI-Prolog:
?- List = [A, B, C, D], nth1(3, List, this_is_the_third_element).
List = [A, B, this_is_the_third_element, D],
C = this_is_the_third_element.
So an alternative implementation of your predicate simply calls nth1/3 for each of your (Index, Element) pairs:
solve(_List, []).
solve(List, [(Index, Elem) | Pairs]) :-
nth1(Index, List, Elem),
solve(List, Pairs).
And with this you're done:
?- E = [A, B, C, D], L = [(1, b), (3, m)], solve(E, L).
E = [b, B, m, D],
A = b,
C = m,
L = [(1, b), (3, m)] ;
false.
Note that this solution is simple, but it has quadratic complexity in the length of the input list: nth1/3 might have to visit the entire N-element list N times. In the unlikely case that you need this predicate for a performance-critical part of some larger program, consider the more optimized solution sketched in the other answer.
Is there any way to do this?
Certainly. And as they say in Perl: "There is more than one way to do it".
Couple of problems:
Do not use (1,b). Use the idiomatic -(1,b) instead, which is written as 1-b (the pair). This gives you a list of pairs: L=[1-b,3-m]. There is a library specifically dealing with such pairs: https://www.swi-prolog.org/pldoc/man?section=pairs - alternatively you can use real maps implemented with AVL trees: https://www.swi-prolog.org/pldoc/man?section=assoc
Now you just need to:
sort the list of pairs, probably using keysort: https://www.swi-prolog.org/pldoc/doc_for?object=sort/2 or https://www.swi-prolog.org/pldoc/doc_for?object=sort/4
Go through the list left to right, keeping the current index, and performing a replacement when the next key in your sorted list is hit, or just retaining the existing term from the list otherwise. The result goes into an accumulator variable as head of a list.
Done! Special handling of out-of-bounds indexes etc. to be suitably handled by throwing or failing.
How to go through the sorted list of pairs (I didn not test this!):
% case of Index hit:
go_through([Index-Value|Rest],Index,InList,OutList) :-
InList = [I|Rest],
OutList = [Value|More],
succ(Index,NextIndex),
go_through(Rest,NextIndex,Rest,More).
% case of Index miss:
go_through([NotYetIndex-Value|Rest],Index,InList,OutList) :-
NotYetIndex > Index, % that should be the case
InList = [I|Rest],
OutList = [I|More],
succ(Index,NextIndex),
go_through(Rest,NextIndex,Rest,More).
go_through([],_,L,L). % DONE
Alternatively, you can write a replace0 that replaces-by-index in a list, and go through the L list.
Addendum: Working code using go_through
Actually contains a few subtlties
another_vectorial_replace1(ListIn,ReplacePairs,ListOut) :-
maplist([_,_]>>true,ListIn,ListOut), % Bonus code: This "makes sure" (i.e. fails if not)
% that ListIn and ListOut are the same length
maplist([(A,B),A-B]>>true,ReplacePairs,RealPairs), % Transform all (1,b) into [1,b]
maplist([K-_]>>integer(K),RealPairs), % Make sure the RealPairs all have integers on first place
keysort(RealPairs,RealPairsSorted), % Sorting by key, which are integers; dups are not removed!
debug(topic,"ListIn: ~q",[ListIn]),
debug(topic,"RealPairsSorted: ~q",[RealPairsSorted]),
go_through(RealPairsSorted,1,ListIn,ListOut),
debug(topic,"ListOut: ~q",[ListOut]).
% Case of Index hit, CurIndex is found in the first "Replacement Pair"
go_through([CurIndex-Value|RestPairs],CurIndex,ListIn,ListOut) :-
!, % Commit to choice
ListIn = [_|Rest],
ListOut = [Value|More],
succ(CurIndex,NextIndex),
go_through(RestPairs,NextIndex,Rest,More).
% Case of Index miss:
go_through([NotYetIndex-V|RestPairs],CurIndex,ListIn,ListOut) :-
NotYetIndex > CurIndex, % that should be the case because of sorting; fail if not
!, % Commit to choice
ListIn = [X|Rest],
ListOut = [X|More],
succ(CurIndex,NextIndex),
go_through([NotYetIndex-V|RestPairs],NextIndex,Rest,More).
% Case of DONE with list traversal
% Only succeed if there are not more pairs left (i.e. no out-of-bound replacements)
go_through([],_CurIndex,L,L).
% ===
% Tests
% ===
:- begin_tests(another_vectorial_replace1).
test(empty) :- another_vectorial_replace1([],[],LO),
LO=[].
test(nop_op) :- another_vectorial_replace1([a,b,c,d],[],LO),
LO=[a,b,c,d].
test(one) :- another_vectorial_replace1([a],[(1,xxx)],LO),
LO=[xxx].
test(two) :- another_vectorial_replace1([a,b,c,d],[(4,y),(2,x)],LO),
LO=[a,x,c,y].
test(full) :- another_vectorial_replace1([a,b,c,d],[(1,e),(2,f),(3,g),(4,h)],LO),
LO=[e,f,g,h].
test(duplicate_replacement,[fail]) :- another_vectorial_replace1([a],[(1,x),(1,y)],_).
test(out_of_bounds_high,[fail]) :- another_vectorial_replace1([a],[(2,y)],_).
test(out_of_bounds_low,[fail]) :- another_vectorial_replace1([a],[(0,y)],_).
:- end_tests(another_vectorial_replace1).
rt :- debug(topic),run_tests(another_vectorial_replace1).
Addendum 2
Replacement using maplist/N, foldl/N and library(assoc)
Recursive calls disappear behind the curtain!
https://github.com/dtonhofer/prolog_notes/blob/master/code/vector_replace0.pl
(the following assumes that the indices in the pairs list will be sorted, in increasing order, as the example in the question indicates.)
What you said can be written as one conjunction
E=[A,B,C,D], L=[(1,a),(3,c)], solve(E,L), E=[a,B,c,D].
which you intend to be holding under the proper definition of solve/2 that you seek to find. But isn't it like saying
E=[A|E2], L=[(1,a)|L2],
E2=[B,C,D], L2=[(3,c)],
solve(E2,L2), E2=[B,c,D],
E=[a|E2].
? Although, something doesn't quite fit right, here. c in E2 appears in second position, not 3rd as indicated by its entry in L2.
But naturally, L2 must be indexed from 2, since it is a tail of L which is indexed from 1. So we must make this explicit:
E=[A,B,C,D], L=[(1,a),(3,c)], solve(E,L), E=[a,B,c,D]
==
E=[A,B,C,D], L=[(1,a),(3,c)], solve(E,1,L), E=[a,B,c,D] % starting index 1
==
E=[A|E2], L=[(1,a)|L2],
E2=[B,C,D], L2=[(3,c)],
solve(E2,2,L2), E2=[B,c,D], E=[a|E2]
must, and now can, hold. But where did a get from, in E? What we actually mean here is
E=[A|E2], L=[(1,a)|L2],
p( (1,a), 1, a), % index match
E2=[B,C,D], L2=[(3,c)],
solve(E2,2,L2), E2=[B,c,D], % starting index 2
E=[a|E2]
with p/3 defined as
p( (I,A), I, A).
And so it must also hold that
E2=[B|E3], L2=[(3,c)],
\+ p( (3,c), 2, c), % index mismatch
E3=[C,D], L3=L2,
solve(E3,3,L3), E3=[c,D], E2=[B|E3]
L2 is not traversed along at this step (L3=L2), since p( (3,c), 2, c) does not hold.
Do you see how the recursive definition of solve/3 reveals itself here? Could you finish it up?

Haskell: converting a list of tuples into a list of lists

I have a list of tuples:
[("book", 1,0), ("book", 2,0), ("title", 2,1)]
that I wanted to convert into a list of lists with the ints converted to Strings as well:
[["book, "1","0"], ["book , "2", "0"]...]
I tried:
map(\(a, b, c) -> [a, b, c])myList
but I get the following error message:
* No instance for (Num [Char]) arising from a use of `myList'
You can not perform that conversion. Lists, unlike tuples are homogeneous: they contain values of the same type, only.
There's no such a list as ["book",1,0], since it contains both strings and numbers. That list can not have type [String], nor type [Int], for instance.
In addition to #chi's answer, you may also try a sum of Int and String, called Either Int String.
concatMap
(\(s, x, y) -> [Right s, Left x, Left y])
[("book", 1, 0), ("book", 2, 0), ("title", 2, 1)]
= [Right "book", Left 1, Left 0, Right "book",
Left 2, Left 0, Right "title", Left 2, Left 1]
If the numbers are to be associated with the string, however, the list of tuples is a superior structure.
If you are sure that your tuple is of type (String, Int, Int) then you just write
tupleToList :: (String, Int, Int) -> [String]
tupleToList (a,b,c) = [a, show b, show c]
and map it over what you have, [(String, Int, Int)].
More generally,
tupleToList :: (Show a, Show b) => (String, a, b) -> [String]
tupleToList (a,b,c) = [a, show b, show c]
which allows you to insert any displayable thing in 2nd and 3rd place of the input tuple, but not being more general: for example, you can not have
Unfixed length of tuple, like (a,b,c) mixing with (a,b,c,d)
Switching the show objects, like (String, a, b) mixing (b, String, a)
-- I mean, how would you store the different tuples in a list in the first place?
In case of that you really want, there is something called Heterogenous list which is never recommended and you cannot really get much out of it.

Compare the first item of a list with the last one of another list in prolog

I am trying to compare two different lists, but the comparation must be succesful when the first and the last items of the lists are equal and vice versa, while the other items of the lists must be equal.
So the thing must be that
cmp([a,b,c,d,e],[e,b,c,d,a]).
true.
With the following code we succeed but only with the first two items of the lists:
swap([X,Y],[Y,X]).
swap([X,Y|T],[Y,X|Z]):- T=Z.
Some idea?
I like the append/3 approach that #gusbro presented (+1). Another way to do this is with an auxiliary predicate that carries the elements you want along. This is a minor variation on the problem of swapping the first and last elements of a list.
cmp([A|As], [B|Bs]) :-
cmp(As, A, B, Bs).
cmp([A], B, A, [B]).
cmp([_, A|As], X, Y, [_, B|Bs]) :-
cmp([A|As], X, Y, [B|Bs]).
| ?- cmp([a,b,c,d,e],[e,b,c,d,a]).
true ? a
no
| ?- cmp(A, B).
A = [C,D]
B = [D,C] ? ;
A = [C,_,D]
B = [D,_,C] ? ;
A = [C,_,_,D]
B = [D,_,_,C] ? ;
A = [C,_,_,_,D]
B = [D,_,_,_,C] ? ;
...
I would use append/3 to get the first and last item, and use it again with those items interchanged:
cmp(A, B):-
append([First|Tail], [Last], A),
append([Last|Tail], [First], B).

Add sum of values of two lists into new one in scala

v1 = [1,2,3,4]
v2 = [1,2,3,4,5]
I need the sum of these lists: [2,4,6,8,5]
And is there any way to print elements that executes a+b= c , where c is for example 8 ?
How can I do that in scala?
You can use zipAll to zip the lists together. That method takes in two extra arguments that represents the element to use in case one list is longer than the other, and vice versa. Since you are adding the lists, you should use the additive identity 0. Then you can simply map over the generated list of tuples:
val v1 = List(1, 2, 3, 4)
val v2 = List(1, 2, 3, 4, 5)
v1.zipAll(v2, 0, 0).map { case (a, b) => a + b }
You can read the documentation of zipAll in the documentation of IterableLike. The most relevant part:
Returns a iterable collection formed from this iterable collection and another iterable collection by combining corresponding elements in pairs. If one of the two collections is shorter than the other, placeholder elements are used to extend the shorter collection to the length of the longer.
If you're looking to print out certain elements, you might choose to filter instead of map, and then use foreach:
v1.zipAll(v2, 0, 0).filter {
case(a, b) => a + b == 8
}.foreach {
case(a, b) => println(s"$a+$b=8")
}
Or just a foreach with more interesting case statements:
v1.zipAll(v2, 0, 0).foreach {
case(a, b) if a + b == 8 => println(s"$a+$b=8")
case _ =>
}
Or you could use collect, and ignore the return value:
v1.zipAll(v2, 0, 0).collect {
case(a, b) if a + b == 8 => println(s"$a+$b=8")
}
You might want to read some introductory text to the Scala collections library, like the one in the docs.
A similar approach to Ben's, using a for comprehension,
for ( (a,b) <- v1.zipAll(v2, 0, 0) if a+b == 8 ) yield (a,b)
which delivers those (zipped) pairs of values whose sum is 8.

Scala list of list count different elements per sublist index

I have a list of lists with the following data
val list = List(List("a","b","c"),List("d","e","f"),List("a","a","a"))
I want to disicover how many different data do I have in each position of the sublists
1 -> List("a","d","a")
2 -> List("b","e","a")
3 -> List("c","f","a")
Is there a way to do that? It doesn't need to be indexed, but I need the amount of different values per sublist index, the result could also be
2 // different values a and d
3 // different values b, e and a
3 // different values c, f and a
As I noted in a comment on Jhonny Everson's (almost right but now deleted) answer, you can use transpose to get a list of the columns, and then distinct to remove duplicates:
scala> list.transpose.map(_.distinct.size)
res0: List[Int] = List(2, 3, 3)
This will throw an exception if all the lists don't have the same size, but that's probably what you want.
scala> list.transpose.map(_.toSet.size)
res0: List[Int] = List(2, 3, 3)
The output of list.transpose is List(List(a, d, a), List(b, e, a), List(c, f, a)) which gives you the structure you want then map each List to a Set to get the unique elements and count them.
If you want unique elements per position, then you can use zipWithIndex and reverse the outputs.
scala> list.transpose.map(_.distinct).zipWithIndex.map(t => t._2 -> t._1)
res1: List[(Int, List[String])] = List((0,List(a, d)), (1,List(b, e, a)), (2,List(c, f, a)))
Here is the code you wanted:
var lOfl = List(List.range(1,5), List(2,2,2,3), Nil)
//> lOfl : List[List[Int]] = List(List(1, 2, 3, 4), List(2, 2, 2, 3), List())
for {
l <- lOfl
} yield l.toSet.count(_ => true) //> res1: List[Int] = List(4, 2, 0)
A sample list of list of Int is created as lOfl; for loop iterates through each list of Int; toSet converts list to set eliminating duplicate elements. then count function does as the name says it all.
OR use the Scala's most used collection function (:P :P), map, like below,
lOfl.map(l => l.toSet.count(_ => true) ) //> res2: List[Int] = List(4, 2, 0)