F# Parse Excel File Into Tuple Array - excel

I have a follow up question on this post. I would like to take the contents of an Excel spreadsheet and put it into a Array of tuples where each tuple corresponds to each row in the spreadsheet.
I started with looping though the entire range like this:
let path = "XXX.xlsx"
let app = ApplicationClass(Visible = false)
let book = app.Workbooks.Open path
let sheet = book.Worksheets.[1] :?> _Worksheet
let content = sheet.UsedRange.Value2 :?> obj[,]
for i=content.GetLowerBound(0) to content.GetUpperBound(0) do
for j=content.GetLowerBound(1) to content.GetUpperBound(1) do
But strikes me as very inefficient. If there something in the base API spec out of the box that I can use?
Thanks in advance

The Array2D module implements some common functions for 2D arrays.
I am guessing you want to use Array2D.iter or Array2D.iteri to replace your for loop.

The straightforward way to convert each row (of a two-dimensional array) to a tuple (in a single-dimensional row) is to finish what you started - just iterate over all the rows and construct a tuple:
let tuples =
[ for i in contents.GetLowerBound(0) .. contents.GetUpperBound(0) ->
contents.[i,0], contents.[i,1], contents.[i,2] ]
To do this, you need to know (statically) what is the length of the row. This is because F# tuples are fixed-length tuples and the length is checked. The above example assumes that there are just 3 elements with indices 0, 1 and 2. If the length is dynamic, then you probably should continue using 2D arrays rather than a list of tuples.

Another option is to bypass the Excel engine altogether. There are a couple of ways of doing this, but the one I've had great success with is 'SpreadsheetGear'. It isn't free (bring on the downvotes), but it replicates the Excel API very closely and is very fast.

Related

Most practical way to add a value to a particular list, based on a variable

The title may sound a bit weird, but the situation is not so much.
I have some lists.
Here they are initialized (global variables):
sensor0, sensor1, sensor2, sensor3 = ([] for i in range(4))
Now we have a variable that indicates the list that i can insert data to. Let's say it's selector = 3.
This means i should append() my value to the sensor3 list.
What is the most practical way to do this in python?
If it was a C style language, i would use a switch-case.
But there is no switch-case syntax in python. Of course i could do multiple ifs, but this seems not the best way to do it.
I wonder, since there is only one letter to the lists that change everytime, perhaps there is a better way to select the proper list to append() to, based on the selector variable.
For your specific case, use eval
sensor0, sensor1, sensor2, sensor3 = ([] for i in range(4))
sensor3 = 20
selector =3
result = eval("sensor"+str(selector))
print(result)
But using a list may be a better option.
Using List
sensor = [[] for i in range(4)]
selector = 3
sensor[selector] = 20
print(sensor[selector])

list of one string element getting converted to list of characters

I have a program which receives input from another program and use it for further operations. The input can be a list, set, tuple but for further operations a list is needed. So I am converting input to list.
The problem arises when input my program receives is a list/set/tuple with just one element like below. The
import itertools
def not_mine(c):
d = {'John':['mid', 'forward'],
'Lana':['mid'],
'Jacob':['defence', 'mid'],
'Ian':['goal', 'mid']}
n = itemgetter(*c)(d)
n = list(set(itertools.chain.from_iterable(n)))
return n
def mine(c):
name = not_mine(c)
name_1 = list(name)
print(name_1)
mine(['Jacob', 'Ian'])
['defence', 'goal', 'mid']
mine(['Lana'])
['i', 'm', 'd']
Is there any way to prevent the second case? It should be a list of one element ['mid'].
Iterators
The function set uses the first argument as an iterator to create a sequence of items. str is natively an iterator. In other words, you can loop over a str and you'll assign to the for variable each character in the string per iteration.
for whatami in "hi!":
print(whatami)
h
i
!
If you want to treat a single string input as a single item, explicitly pass an iterator argument to set (list works the same way, BTW) with a single item in it. Tuple is, also, an iterator. Let's try to use it to prove our theory
t1 = ('ourstring', )
print(f"t1 is of type {type(t1)}")
s1 = set(t1)
print(s1)
t1 is of type <class 'tuple'>
{'ourstring'}
It works!
What we've done with ('ourstring', ) is explicitly define a tuple with one item. There's a familiar delimiter, ,, used to say "this tuple is instantiated with only one item".
Input
To separate situations between ingesting a list of items and one string item, you can consider two approaches.
The most straight-forward way is to agree on a delimiter in the input such as comma separated values. firstvalue,secondvalue,etc. The down side of this is that you'll quickly run into limitations of what kind of data you can receive.
To ease your development, argparse is strongly recommended command line arguments. It is a built-in, battle-hardened package made for this type of task. The docs's first example even shows a multi-value field.

On a dataset made up of dictionaries, how do I multiply the elements of each dictionary with Python'

I started coding in Python 4 days ago, so I'm a complete newbie. I have a dataset that comprises an undefined number of dictionaries. Each dictionary is the x and y of a point in the coordinates.
I'm trying to compute the summatory of xy by nesting the loop that multiplies xy within the loop that sums the products.
However I haven't been able to figure out how to multiply the values for the two keys in each dictionary (so far I only got to multiply all the x*y)
So far I've got this:
If my data set were to be d= [{'x':0, 'y':0}, {'x':1, 'y':1}, {'x':2, 'y':3}]
I've got the code for the function that calculates the product of each pair of x and y:
def product_xy (product_x_per_y):
prod_xy =[]
n = 0
for i in range (len(d)):
result = d[n]['x']*d[n]['y']
prod_xy.append(result)
n+1
return prod_xy
I also have the function to add up the elements of a list (like prod_xy):
def total_xy_prod (sum_prod):
all = 0
for s in sum_prod:
all+= s
return all
I've been trying to find a way to nest this two functions so that I can iterate through the multiplication of each x*y and then add up all the products.
Make sure your code works as expected
First, your functions have a few mistakes. For example, in product_xy, you assign n=0, and later do n + 1; you probably meant to do n += 1 instead of n + 1. But n is also completely unnecessary; you can simply use the i from the range iteration to replace n like so: result = d[i]['x']*d[i]['y']
Nesting these two functions: part 1
To answer your question, it's fairly straightforward to get the sum of the products of the elements from your current code:
coord_sum = total_xy_prod(product_xy(d))
Nesting these two functions: part 2
However, there is a much shorter and more efficient way to tackle this problem. For one, Python provides the built-in function sum() to sum the elements of a list (and other iterables), so there's no need create total_xy_prod. Our code could at this point read as follows:
coord_sum = sum(product_xy(d))
But product_xy is also unnecessarily long and inefficient, and we could also replace it entirely with a shorter expression. In this case, the shortening comes from generator expressions, which are basically compact for-loops. The Python docs give some of the basic details of how the syntax works at list comprehensions, which are distinct, but closely related to generator expressions. For the purposes of answering this question, I will simply present the final, most simplified form of your desired result:
coord_sum = sum(e['x'] * e['y'] for e in d)
Here, the generator expression iterates through every element in d (using for e in d), multiplies the numbers stored in the dictionary keys 'x' and 'y' of each element (using e['x'] * e['y']), and then sums each of those products from the entire sequence.
There is also some documentation on generator expressions, but it's a bit technical, so it's probably not approachable for the Python beginner.

Julia: empty vector of strings

I'd like to initialize an empty vector and then add strings to it. However, using x=[] creates an empty array of type Any. I've read that specifying types improves performance.
I tried x = Vector{String} but other functions (append, join and push) don't work as expected.
Is it possible to creates an empty array of strings to further append strings to it?
You can do it in two ways:
vs = String[]
or
vs = Vector{String}()

Simple adding two arrays using numpy in python?

This might be a simple question. However, I wanted to get some clarifications of how the following code works.
a = np.arange(8)
a
array([1,2,3,4,5,6,7])
Example Function = a[0:-1]+a[1:]/2.0
In the Example Function, I want to draw your attention to the plus sign between the array a[0:-1]+a[1:]. How does that work? What does that look like?
For instance, is the plus sign (addition) adding the first index of each array? (e.g 1+2) or add everything together? (e.g 1+2+2+3+3+4+4+5+5+6+6+7)
Then, I assume /2.0 is just dividing it by 2...
A numpy array uses vector algebra in that you can only add two arrays if they have the same dimensions as you are adding element by element
a = [1,2,3,4,5]
b = [1,1,1]
a+b # will throw an error
whilst
a = [1,2,3,4,5]
b = [1,1,1,1,1]
a+b # is ok
The division is also element by element.
Now to your question about the indexing
a = [1,2,3,4,5]
a[0:-1]= [1,2,3,4]
a[1:] = [2,3,4,5]
or more generally a[index_start: index_end] is inclusive at the start_index but exclusive at the end_index - unless you are given a a[start_index:]where it includes everything up to and including the last element.
My final tip is just to try and play around with the structures - there is no harm in trying different things, the computer will not explode with a wrong value here or there. Unless you trying to do so of course.
If arrays have identical shapes, they can be added:
new_array = first_array.__add__(second_array)
This simple operation adds each value from first_array to each value in second_array and puts result into new_array.

Resources