This question already has an answer here:
Prolog flatten list
(1 answer)
Closed 1 year ago.
How can I flatten a list in Prolog, for example:
from A = [["a","b"],["c"]]
to B = ["a", "b", "c"] ?
A list can be flattened using maplist and append, in the following way.
A two-level list may be flattened as shown.
?- A=[["a","b"],["c"]],maplist(append,[A],[B]).
A = [["a", "b"], ["c"]],
B = ["a", "b", "c"].
A three-level may be flattened with two passes of the command.
?- A=[[["a","b"]],[["c"]]],maplist(append,[A],[B]),maplist(append,[B],[C]).
A = [[["a", "b"]], [["c"]]],
B = [["a", "b"], ["c"]],
C = ["a", "b", "c"].
Mixtures of two and three levels in a list results in an error from two passes of the command.
?- A=[[["a","b"]],[["c"]],["d"]],maplist(append,[A],[B]),maplist(append,[B],[C]).
false.
Mixtures of two and three levels in a list can only be partially flattened with one pass of the command.
?- A=[[["a","b"]],[["c"]],["d"]],maplist(append,[A],[B]).
A = [[["a", "b"]], [["c"]], ["d"]],
B = [["a", "b"], ["c"], "d"].
Related
I want to create a predicate shift(List1,List2) where List2 is List1 shifted rotationally by one element to the left.
Example:
?- shift([1,2,3,4],L1), shift(L1,L2), shift(L2,L3).
L1 = [2, 3, 4, 1],
L2 = [3, 4, 1, 2],
L3 = [4, 1, 2, 3].
I created the predicate
conc([],L,L).
conc([X|T],L2,[X|T1]) :-
conc(T,L2,T1).
shift([H|T],L2) :-
conc(T,H,L2).
However, it's wrong & I don't understand why... It works only if the H is surrounded by [H].
shift([H|T],L2) :-
conc(T,[H],L2).
The predicate without the [ ] only works with 1 shift & it outputs the following:
?- shift([1,2,3,4],L1).
L1 = [2, 3, 4|1].
Obviously, there's a basic concept I'm confused with, but I can't seem to pin-point what's wrong alone. I'm new at Prolog, so any help would be appreciated.
It works only if the H is surrounded by [H]
As I noted before, conc/3 is really the standard predicate append/3 which takes in two list and creates a third list.
append/3 says:
append(?List1, ?List2, ?List1AndList2)
List1AndList2 is the concatenation of List1 and List2
A single term is not a list, e.g. 1 is not a list, but [1] is a list.
A list starts with [ and ends with ].
This is the empty list: []
A list can have one item: [a]
or more than one item: [a,b] and so on. Notice how they always have square brackets.
When you use conc/3 or append/3 all three values have to be list, so even if you want to concatenate or append a single item you have to convert it to a list first by surrounding it with [] to turn it into a list. So the single item 1 is converted to a list as [1].
I have two lists that I need to merge into a new list, but the new list needs to contain merged indexes of the original lists. For example:
List1 = [1, 2, 3]
List2 = [a, b, c]
I need the output to be:
finalList = [1a, 2b, 3c]
I need to be able to do this in groovy. I appreciate any help you can provide.
Assuming both lists are the same size, in Groovy 2.4+,
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
assert ['1a', '2b', '3c'] == list1.withIndex().collect { it, index -> it + list2[index] }
Alternatively and a bit more simply in Groovy 1.5+,
assert ['1a', '2b', '3c'] == [list1, list2].transpose()*.sum()
The following is very close to doelleri's solution:
In Groovy 2.4+
println ([list1, list2].transpose().collect{it -> it[0] + it[1]})
OUTPUT
[1a, 2b, 3c]
I've a problem with the nested lists. I want to compute the lenght of the intersection of two nested lists with the python language. My lists are composed as follows:
list1 = [[1,2], [2,3], [3,4]]
list2 = [[1,2], [6,7], [4,5]]
output_list = [[1,2]]
How can i compute the intersection of the two lists?
I think there are two reasonable approaches to solving this issue.
If you don't have very many items in your top level lists, you can simply check if each sub-list in one of them is present in the other:
intersection = [inner_list for inner in list1 if inner_list in list2]
The in operator will test for equality, so different list objects with the same contents be found as expected. This is not very efficient however, since a list membership test has to iterate over all of the sublists. In other words, its performance is O(len(list1)*len(list2)). If your lists are long however, it may take more time than you want it to.
A more asymptotically efficient alternative approach is to convert the inner lists to tuples and turn the top level lists into sets. You don't actually need to write any loops yourself for this, as map and the set type's & operator will take care of it all for you:
intersection_set = set(map(tuple, list1)) & set(map(tuple, list2))
If you need your result to be a list of lists, you can of course, convert the set of tuples back into a list of lists:
intersection_list = list(map(list, intersection_set))
What about using sets in python?
>>> set1={(1,2),(2,3),(3,4)}
>>> set2={(1,2),(6,7),(4,5)}
>>> set1 & set2
set([(1, 2)])
>>> len(set1 & set2)
1
import json
list1 = [[1,2], [2,3], [3,4]]
list2 = [[1,2], [6,7], [4,5]]
list1_str = map(json.dumps, list1)
list2_str = map(json.dumps, list2)
output_set_str = set(list1_str) & set(list2_str)
output_list = map(json.loads, output_set_str)
print output_list
the Nested List can exist in Scheme, but is it legal to use nested-list in SML? or we can only use simple list in SML?
and if legal,
1) how to check wether the two input list have the same list structure. algorithm the atoms in the list are not equal.
2) Whatever the deep of the input list, how to delete all the atoms in the nested-list that equals to the input value: a. should use the original list and not create a new list.
There's no problem in having nested lists in Standard ML. For an example:
val foo = [ [1, 2, 3], [4, 5], [6] ]
is an example of an int list list, i.e., a list of lists of integers.
As for your additional questions.
1
If by same structure you mean whether the sublists contain the same number of elements, i.e, you want
val bar = [ [34, 4, 6], [2, 78], [22] ]
val baz = [ [1], [4, 6, 2], [3, 6] ]
val cmp_foo_bar = structureEq (foo, bar) (* gives true, since the lengths of the sublists match up *)
val cmp_foo_baz = structureEq (foo, baz) (* gives false, since they don't *)
Then you can simply make a recursive function on the lists, that compares the length of each sublist in turn.
Note, if the lists are nested more than once, you'll need a function for each level. (i.e., one for 'a list lists, one for 'a list list lists, etc.
2
You cannot make a function that "however deep the input list" does something to the elements in the list. The type system will not let you do this. This is similar to how you cannot make the following list:
val illegal_list = [ [1, 2], [ [1, 4], [2, 3] ] ]
This is due to a list only being allowed to contain one type of elements, so if you have an 'a list list, each element in the list must be an 'a list. You cannot have 'as directly.
You'll have to settle on how nested the lists are, and make a function specific to that depth.
There is no problem with nesting lists in SML, e.g. [[1, 2], [3, 4]] works just fine.
However, I suspect you actually mean something more general, namely the ability to nest "lists" in heterogeneous ways: [[1, [3]], 2]. This is not legal as such in SML. However, this is because such a thing is not really a list, it is a tree.
You can define trees easily as well, but you need a more general type definition than the one for list:
datatype 'a tree = L of 'a | T of 'a tree list
Then T[T[L 1, T[L 3]], L 2] is a representation of the "list" above. A function for computing the depth (or height) of such a tree looks like
fun depth (L _) = 0
| depth (T ts) = 1 + max (List.map depth ts)
where max needs to be defined in the obvious manner.
I have a list of lists (in erlang, strings are lists) which looks like this:
["abc","def"]
and I would like to get the following combinations in a list returned by a function:
["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]
Is it possible with list-comprehension? I don't know the dimension of the list beforehand
If you don't know the dimension of the input, then you need to use recursion as #legoscia said:
cartesian([H]) -> [[A] || A <- H];
cartesian([H|T]) -> [[A|B] || A <- H, B <- cartesian(T)].
A 1-dim input "abc" is turned into ["a", "b", "c"], everything else is recursion.
> cartesian:cartesian(["abc", "def", "ghi"]).
["adg","adh","adi","aeg","aeh","aei","afg","afh","afi",
"bdg","bdh","bdi","beg","beh","bei","bfg","bfh","bfi","cdg",
"cdh","cdi","ceg","ceh","cei","cfg","cfh","cfi"]
Edit: Or easier, yet: Let a 0-dim argument return the set that contains the empty set. I think that's what a mathematician would do, too.
cartesian([H|T]) -> [[A|B] || A <- H, B <- cartesian(T)];
cartesian([]) -> [[]].
If you have exactly two lists, then you can do it with a list comprehension like this:
1> [[X,Y] || X <- "abc", Y <- "def"].
["ad","ae","af","bd","be","bf","cd","ce","cf"]
If you have an arbitrary number of lists, you could do it with a list comprehension inside a recursive function.