Simple Syntax Question (tuple conversion) - python-3.x

I'm currently researching different ways to combine, organize and manipulate data for different purposes.
Just today I found this zip() / iter() technique of creating a LIST containing TUPLES while also being able to specify how many elements are in each TUPLE. However, I'm unable to fully understand part of the syntax.
Here is the code:
mylist = [1,2,3,4,5,6]
converted = [x for x in zip(*[iter(mylist)]*2)]
print(converted)
This is the output (which is what I want):
[(1, 2), (3, 4), (5, 6)]
What I'm trying to grasp is the first asterisk. I understand that it's most likely in relation to the '*2' telling the 'iter' or 'zip' function how many elements each tuple should contain, however, I'm trying to grasp the need for it's placement.
Any help is greatly appreciated.
Also, if you know of another technique to accomplish this and feel like sharing, I'd greatly appreciate learning from you.
Thanks again in advance guys!

Basically iter(mylist) makes an iterator object for the list, then it's put into a list [iter(mylist)] which is multiplied by 2 basically making a list that contains two references to the same iterator object: [iter(mylist)]*2 -> [<list_iterator object at 0x7f8fbc1ac610>, <list_iterator object at 0x7f8fbc1ac610>]
The first asterisk unpacks the list as arguments into the zip() function.
To make it easier to understand as I'm not very good at explaining things, this code does the same as yours:
mylist = [1,2,3,4,5,6]
iterators = [iter(mylist)] * 2
converted = [x for x in zip(*iterators)]
print(converted)
So it makes an iterator, then it makes a list that contains two references to the same iterator object by multiplying it by 2.
And then it unpacks the list to be used as arguments for the zip() function
I hope this cleared it up at least a little for you as I'm not very good at explaining.

Related

how to get a zig zag pattern between two array?

I am trying to find the zig zag pattern between two arrays. I've come across posts where 1 array is used. I understand the logic of it but even when i append the two lists together, I am unable to get the desired output.
arr1 = [1,2,3,4,5]
arr2 = [6,7,8,9,10]
expected_output = [5,9,3,7,1,6,2,8,4,10]
any hint to solve it would help. P.S I am still learning programming, so if i missed an obvious pattern, do let me know. thanks!

How to type hint a list with different types in specific positions

I'm trying to type hint a list that contains multiple types in a specific order. Something like:
l: list[str, int] = ["text", 10]
Where the first element will always be a str and the second always an int.
MyPy doesn't accept this as list takes exactly 1 argument. If this were a tuple it would work perfectly well, but I need this to be mutable. If there is a data structure other than a list that would work I'd be open to that. I could probably make a custom class that would behave the way I want, but that seems excessive.
Is there a better way to do this?

Comprehension with Lists of Dictionaries

I know this isn't exactly the first question about list comprehensions, but I've been looking around and experimenting for a while and can't figure this one out. I'll apologize in advance, I'm a self-taught novice learning from failures.
This is working code, but it screams list comprehension. I understand list comprehensions and use them, but the combination of stacking for and working with the dictionaries within the lists is breaking my brain. How would you simplify this:
results = []
for system in systems: # list of dicts
for result in telnet_results: # list of dicts
if system['master_ip'] == result['master_ip']:
combined = {**system, **result} # merge dicts, right takes precedence
results.append(combined)
Thanks in advance for any help on this.
results = [{**system, **result} for system in systems for result in telnet_results if
system['master_ip'] == result['master_ip']]
Can be also splitted more logically:
results = [{**system, **result}
for system in systems
for result in telnet_results
if system['master_ip'] == result['master_ip']]
Is this "simplified"? I'm not sure. List comprehensions are not magic, and they do not always simplify the code or make it more readable.

How do I declare and use a lot of variables in Python at one time?

I am a student doing scientific calculations recently,usually,I use odeint function to solve Differential equations,now I need to solve a differential equation system with 100 variables.If I follow my previous programming style in python,I will act like this:
def XFunction(X,t,sets):
x1,x2,x3,x4,,,,,,x100=X
lambd=sets
return np.array([equation1,equation2,equation3,,,,,equation100])
But this method takes too long, is there a more efficient way to do this?
Yes, using integer suffixes like that indicates that you probably want to use sequence like a list or array, but a mapping, like a dict could also work. So instead of x1,x2,x3..., you write X[0], X[1], X[2]... when you need them without pulling them out into locals first. X might already be an array in your program.
If it's just an iterable and not a sequence, you can save it in a list first,
X = [*X]
Which lets you use the subscript operator X[i].
You don't normally "declare" variables in Python, that's implied by assignment, although you can declare without assignment by giving it a (type) annotation.
The [equation1, ...] part could perhaps be done with a list comprehension, which is like a mathematical set comprehension, but ordered.
Here's a stupid example with a single map and filter step. (You can have multiple filters or no filters, but you must use at least one loop.)
[x**2 for x in X if x % 2 == 0]
This list comprehension would generate a list of all squares of the elements of X where the element was even.
I don't know what set of formulae you need for your application, but if it can be parameterized by X, you can do it this way.

How do I get Mathematica to thread a 2-variable function over two lists, using functional programming techniques?

Lets say I have a function f[x_, y_], and two lists l1, l2. I'd like to evaluate f[x,y] for each pair x,y with x in l1 and y in l2, and I'd like to do it without having to make all pairs of the form {l1[[i]],l2[[j]]}.
Essentially, what I want is something like Map[Map[f[#1, #2]&, l1],l2] where #1 takes values from l1 and #2 takes values from l2, but this doesn't work.
(Motivation: I'm trying to implement some basic Haskell programs in Mathematica. In particular, I'd like to be able to code the Haskell program
isMatroid::[[Int]]->Bool
isMatroid b =and[or[sort(union(xs\\[x])[y]'elem'b|y<-ys]|xs<-b,ys<-b, xs<-x]
I think I can do the rest of it, if I can figure out the original question, but I'd like the code to be Haskell-like. Any suggestions for implementing Haskell-like code in Mathematica would be appreciated.)
To evaluate a function f over all pairs from two lists l1 and l2, use Outer:
In[1]:= Outer[f, {a,b}, {x,y,z}]
Out[1]:= {{f[a,x],f[a,y],f[a,z]}, {f[b,x],f[b,y],f[b,z]}}
Outer by default works at the lowest level of the provided lists; you can also specify a level with an additional argument:
In[2]:= Outer[f, {{1, 2}, {3, 4}}, {{a, b}, {c, d}}, 1]
Out[2]:= {{f[{1,2},{a,b}], f[{1,2},{c,d}]}, {f[{3,4},{a,b}], f[{3,4},{c,d}]}}
Note that this produces a nested list; you can Flatten it if you like.
My original answer pointed to Thread and MapThread, which are two ways to apply a function to corresponding pairs from lists, e.g. MapThread[f,{a,b},{1,2}] == {f[a,1], f[b,2]}.
P.S. I think as you're learning these things, you'll find the documentation very helpful. There are a lot of general topic pages, for example, applying functions to lists and list manipulation. These are generally linked to in the "more about" section at the bottom of specific documentation. This makes it a lot easier to find things when you don't know what they'll be called.
To pick up on OP's request for suggestions about implementing Haskell-like code in Mathematica. A couple of things you'll have to deal with are:
Haskell evaluates lazily, by default Mathematica does not, it's very eager. You'll need to wrestle with Hold[] and its relatives to write lazily evaluating functions, but it can be done. You can also subvert Mathematica's evaluation process and tinker with Prolog and Epilog and such like.
Haskell's type system and type checking are probably more rigorous than Mathematica's defaults, but Mathematica does have the features to implement strict type checking.
I'm sure there's a lot more but I'm not terribly familiar with Haskell.
In[1]:= list1 = Range[1, 5];
In[2]:= list2 = Range[6, 10];
In[3]:= (f ## #) & /# Transpose[{list1, list2}]
Out[3]= {f[1, 6], f[2, 7], f[3, 8], f[4, 9], f[5, 10]}

Resources