This is a question about rearranging parts of nested lists in Mathematica.
I've got a nested List:
DatenList = {{1, {100, 200}}, {2, {101, 201}}, {3, {102, 202}}};
and want to get another list like
{{1,100},{2,101}}
Is there a neater way than
temp = DatenList[[1 ;; 2, 1]];
temp2 = DatenList[[1 ;; 2, 2]][[;; , 1]];
temp = {temp}~Join~{temp2};
finalList = Transpose[temp]
which yields
{{1, 100}, {2, 101}}
temp2 = DatenList[[1 ;; 2, 2]][[;; , 1]]
can be written shorter as
temp2 = DatenList[[1 ;; 2, 2, 1]]
Otherwise, the whole operation can be done several ways :-
finalList = {#1, First[#2]} & ### DatenList[[1 ;; 2]]
finalList = DatenList[[1 ;; 2]] /. {a_Integer, {b_, _}} :> {a, b}
finalList = Replace[DatenList[[1 ;; 2]], {a_, {b_, _}} :> {a, b}, 1]
finalList = MapThread[{#1, First[#2]} &, Transpose[DatenList[[1 ;; 2]]]]
Related
I'd like to repeat elements of a list based on a predicate.
I tried using the module itertools and a list comprehension
abc = [1,2,3,4,5,6,7,8,9]
result = [ repeat(item,2) if item==3 or item==7 else item for item in abc ]
This doesn't fail at runtime, but the resulting object is not 'flattened'
If I print it, I see
[1, 2, repeat(3, 2), 4, 5, 6, repeat(7, 2), 8, 9]
Is it doable with a list comprehension?
Thanks
This works:
from itertools import repeat
abc = [1,2,3,4,5,6,7,8,9]
result = [x for y in (repeat(item,2) if item==3 or item==7 else [item] for item in abc)
for x in y]
>>> result
[1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9]
The trick here is to put item in its own list [item] and than flatten the now consistently nested list.
to improve readability, put it in two lines:
nested_items = (repeat(item,2) if item==3 or item==7 else [item] for item in abc)
result = [item for nested_item in nested_items for item in nested_item]
Since nested_items is an iterator, there is no extra list created her.
It will need to get the next imput and output:
pospair [1, 3, 9, 2, 5, 7, 1, 11]
[1, 9, 5, 1]
posimpair [1, 3, 9, 2, 5, 7, 1, 11]
[3, 2, 7, 11]
This is the way to obtain the element on the specified index:
show_in_index::Ord a=>[a]->Int->a
show_in_index l n = l!!n
It shows a result like this:
*Main> show_in_index [1,4,2,7,9] 3
7
The most simple way to do this is using recursion:
pospair :: [a] -> [a]
pospair xs = aux xs [] True
where
aux [] acc _ = acc
aux (y:ys) acc True = aux ys (acc ++ [y]) False
aux (y:ys) acc False = aux ys acc True
Note how I use True or False value to keep track of what value to eliminate. If it's False, I don't include the value in acc (accumulator). If it's True, I include the value. Using the same idea, you can implement posimpair.
You could map the function for indexing
For pospair the following works:
map ([1, 3, 9, 2, 5, 7, 1, 11] !! ) [0,2..length [1, 3, 9, 2, 5, 7, 1, 11]-1]
For posimpair we only have to change the second list that is the one that holds the indexing numbers, previously we had the series of pairs and now we want the series of impairs, so instead of having 0,2,.. until the length of the list -1 we have to do it with 1,3,..until the length of the list-1.
map ([1, 3, 9, 2, 5, 7, 1, 11] !! ) [1,3..length [1, 3, 9, 2, 5, 7, 1, 11]-1]
The general implementation is
pospairs = map (list !!) [0,2..length list - 1]
posimpairs = map (list !!) [1,3..length list - 1]
I tested your example and works.
I thought I understood how Python handles copies of mutables, but I came upon the following behavior.
x = [i for i in xrange(5)]
mylist = [x, x]
mylist_copy = mylist[:]
mylist_copy[0].pop()
mylist
Out : [[0, 1, 2, 3], [0, 1, 2, 3]]
So it seems mylist was changed despite changes being made only to mylist_copy. How can I create a pure copy of mylist so that this does not occur?
While you're indeed making a copy, it is a shallow copy: mylist_copy contains references to the original x.
To make a deep copy, use copy.deepcopy().
This happens not because of any copying errors when making mylist_copy, but because mylist is made up of two of the same elements.
mylist = [x,x] adds two references to the same object (`x`).
As a result, mylist[0].pop() will have the same outcome:
In [70]: x = [i for i in range(5)]
In [71]: mylist = [x,x]
In [72]: mylist
Out[72]: [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4]]
In [73]: mylist[0].pop()
Out[73]: 4
In [74]: mylist
Out[74]: [[0, 1, 2, 3], [0, 1, 2, 3]]
Here's one way to circumvent this issue:
In [80]: x = [i for i in range(5)]
In [81]: mylist = [x, x[:]]
In [82]: mylist_copy = mylist[:]
In [83]: mylist_copy[0].pop()
Out[83]: 4
In [84]: mylist
Out[84]: [[0, 1, 2, 3], [0, 1, 2, 3, 4]]
I want a function which takes the product of the inits of a list and duplicates its elements.
For example the list is: [2, 3, 4, 5].
The product of its inits : [1, 2, 6, 24, 120].
At the end the list should look like this: [1, 1, 2, 2, 2, 6, 6, 6, 6, 24, 24, 24, 24, 24].
My problem is that the [1, 2, 6, 24, 120] should not vary, but i can't solve it, I'm pretty new to haskell. You don't need to modify this code, you can make a new one.
makeSystem :: Integral a => [a] -> [a]
makeSystem l= replicate (l !! 0) ((map product(inits l))!!0) ++ asd (tail l) where
inits [] = [[]]
inits (x:xs) = [[]] ++ map (x:) (inits xs)
An other example: makeSystem [5,2,5,2,5,2]
The result: [1, 1, 1, 1, 1, 5, 5, 10, 10, 10, 10, 10, 50, 50, 100, 100, 100, 100, 100, 500, 500]
For the first part, you can use the standard function scanl:
> scanl (*) 1 [2, 3, 4, 5]
[1,2,6,24,120]
For the second part, zipWith with replicate gets us most of the way there:
> zipWith replicate [2, 3, 4, 5] [1, 2, 6, 24, 120]
[[1,1],[2,2,2],[6,6,6,6],[24,24,24,24,24]]
then we just need to concat these lists.
Putting it all together:
> let makeSystem xs = concat $ zipWith replicate xs (scanl (*) 1 xs)
> makeSystem [2, 3, 4, 5]
[1,1,2,2,2,6,6,6,6,24,24,24,24,24]
> makeSystem [5, 2, 5, 2, 5, 2]
[1,1,1,1,1,5,5,10,10,10,10,10,50,50,100,100,100,100,100,500,500]
I'm new to Prolog and I'm having a bit of a hard time understanding how some of the mechanics actually works. Right now I'm trying to work on a particular problem.
I need to find all possible pairs from a single list and so I'm trying to define rules select_pairs(X,Y,_,Z).
Below is what I expect to see when I run the given queries.
The query: select_pairs(X,Y,[1,2,3],Z). returns the following:
X = 1, Y = 2, Zs = [3] ;
X = 1, Y = 3, Zs = [2] ;
X = 2, Y = 1, Zs = [3] ;
X = 2, Y = 3, Zs = [1] ;
X = 3, Y = 1, Zs = [2] ;
X = 3, Y = 2, Zs = [3]
AND the query select_pairs(1,2,Xs,[3]). returns the following:
Xs = [1, 2, 3] ;
Xs = [2, 1, 3] ;
Xs = [1, 3, 2] ;
Xs = [2, 3, 1] ;
Xs = [3, 1, 2] ;
Xs = [3, 2, 1] ;
As of right now, I can only get the first result from the first query to show up and nothing more. What's the best way from me to approach this? Thank you!
Your Prolog should come with select/3, a builtin that's doing exactly what's suggested by its name:
?- select(X,[1,2,3],R).
X = 1,
R = [2, 3] ;
X = 2,
R = [1, 3] ;
X = 3,
R = [1, 2] ;
false.
it also works 'backwards'
?- select(1,R,[2,3]).
R = [1, 2, 3] ;
R = [2, 1, 3] ;
R = [2, 3, 1] ;
false.
Then, to get a working select_pairs/4, you could just combine 2 select/3.