python 3 read array (list?) into new values - arrays

I have the following array, with (I think) sub lists within it:
items = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
I need to read it into new values for future calculations.
For example:
item1 = this
size1 = 5
unit1 = cm
item2 = that
size2 = 3
unit2 = mm
...
There may be more than 3 items in future arrays, so ideally some form of loop is needed?

Arrays in Python can be of 2 types - Lists & Tuples.
list is mutable (i.e. you can change the elements as & when you wish)
tuple is immutable (read only array)
list is represented by [1, 2, 3, 4]
tuple is represented by (1, 2, 3, 4)
Thus, the given array is a list of tuples!
You can nest tuples in lists but not lists in tuples.
This is more pythonic -
items = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
found_items = [list(item) for item in items]
for i in range(len(found_items)):
print (found_items[i])
new_value = int(input ("Enter new value: "))
for i in range(len(found_items)):
recalculated_item = new_value * found_items[i][1]
print (recalculated_item)
Output from above code (taking input as 3)
['this', 5, 'cm']
['that', 3, 'mm']
['other', 15, 'mm']
15
9
45
Update : Following up on this comment & this answer I've updated the above code.

Following on Ashish Nitin Patil's answer...
If there are are going to be more than three items in the future you can use the asterisk to unpack the items in the tuples.
items = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
for x in items:
print(*x)
#this 5 cm
#that 3 mm
#other 15 mm
Note: Python 2.7 doesn't seem to like the asterisk in the print method.
Update:
It looks like you need to use a second list of tuples that defines the property names of each value tuple:
props = [('item1', 'size2', 'unit1'), ('item2', 'size2', 'unit2'), ('item3', 'size3', 'unit3')]
values = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
for i in range(len(values)):
value = values[i]
prop = props[i]
for j in range(len(item)):
print(prop[j], '=', value[j])
# output
item1 = this
size2 = 5
unit1 = cm
item2 = that
size2 = 3
unit2 = mm
item3 = other
size3 = 15
unit3 = mm
The caveat here is that you need to make sure that the elements in the props list are matched sequentially with the elements in the values list.

Related

How to convert strings in a cell array to numerical stand-in values?

In Matlab, I have a cell array of cell arrays created using textscan on a tab-separated data file. Some columns of the data set are strings. Here is an example array, 'data':
data{1,1} = {1; 2; 3; 4; 5};
data{1,2} = {11; 12; 13; 14; 15};
data{1,3} = {'Ringo'; 'Paul'; 'The Beatles'; 'John'; 'George'};
I want to convert the string columns to specific numerical stand-in values (i.e. 'The Beatles' = 1, 'John' = 2, 'Paul' = 3, 'George' = 4, 'Ringo' = 5). Also, it may be important to note that some cells contain more than one "word".
For some context, the entire data set will ultimately be converted from a cell array into one neatly packaged double array (data = cell2mat(data)) for easier manipulation.
The only solution I know is to loop through the string array and use a switch statement:
vec_0 = data{1,3};
for ii = 1:length(vec_0)
switch vec_0{ii}
case 'The Beatles'
vec_f{ii,1} = 1;
case 'John'
vec_f{ii,1} = 2;
case 'Paul'
vec_f{ii,1} = 3;
case 'George'
vec_f{ii,1} = 4;
case 'Ringo'
vec_f{ii,1} = 5;
end
end
% Replace string column with numerical stand-ins
data{1,3} = vec_f;
% Convert cell array to double array
data = cell2mat(data);
Now we have:
data = [1 11 5; 2 12 3; 3 13 1; 4 14 2; 5 15 4];
What is a more optimal way to do this?
If you have a specific mapping of strings to numeric values...
Let's say you have a mapping of strings to numeric values as defined in the following 5-by-2 cell array (one mapping per row):
numMap = {'The Beatles', 1; 'John' , 2; 'Paul' , 3; 'George' , 4; 'Ringo' , 5};
Then you can use ismember to convert the strings to their mapped numeric values and save it back in data like so:
[~, index] = ismember(data{1, 3}, numMap(:, 1));
data{1, 3} = numMap(index, 2);
If you need to generate a mapping of strings to numeric values...
You can generate an array of numerical stand-ins with unique, convert that to a cell array with num2cell, and save it back in data like so:
[uniqueStrings, ~, numIndex] = unique(data{1, 3}, 'stable');
data{1, 3} = num2cell(numIndex);
And uniqueStrings will contain the unique multi-word strings from data{1, 3}.
Converting to a double array:
Once you've chosen one of the above options, you can then convert your sample data to a 5-by-3 double array like so:
data = cell2mat([data{:}]);
data =
1 11 5
2 12 3
3 13 1
4 14 2
5 15 4

Read File and store element as array Scala

I am new to Scala and this is the first time I'm using it. I want to read in a textfile with with two columns of numbers and store each column items in a separate list or array that will have to be cast as integer. For example the textfile looks like this:
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
6 10
I want to separate the two columns so that each column is stored in its on list or array.
Lets say you named the file as "columns", this would be a solution:
val lines = Source.fromFile("columns").getLines()
/* gets an Iterator[String] which interfaces a collection of all the lines in the file*/
val linesAsArraysOfInts = lines.map(line => line.split(" ").map(_.toInt))
/* Here you transform (map) any line to arrays of Int, so you will get as a result an Interator[Array[Int]] */
val pair: (List[Int], List[Int]) = linesAsArraysOfInts.foldLeft((List[Int](), List[Int]()))((acc, cur) => (cur(0) :: acc._1, cur(1) :: acc._2))
/* The foldLeft method on iterators, allows you to propagate an operation from left to right on the Iterator starting from an initial value and changing this value over the propagation process. In this case you start with two empty Lists stored as Tuple an on each step you prepend the first element of the array to the first List, and the second element to the second List. At the end you will have to Lists with the columns in reverse order*/
val leftList: List[Int] = pair._1.reverse
val rightList: List[Int] = pair._2.reverse
//finally you apply reverse to the lists and it's done :)
Here is one possible way of doing this:
val file: String = ??? // path to .txt in String format
val source = Source.fromFile(file)
scala> val columnsTogether = source.getLines.map { line =>
val nums = line.split(" ") // creating an array of just the 'numbers'
(nums.head, nums.last) // assumes every line has TWO numbers only
}.toList
columnsTogether: List[(String, String)] = List((1,2), (2,3), (3,4), (4,5), (1,6), (6,7), (7,8), (8,9), (6,10))
scala> columnsTogether.map(_._1.toInt)
res0: List[Int] = List(1, 2, 3, 4, 1, 6, 7, 8, 6)
scala> columnsTogether.map(_._2.toInt)
res1: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10)

Reduce array to tuple of first and last element?

I have an array that I would like to first sort, then return the first and last element of the sorted array. I thought I can use reduce, but what if I don't have an initial value?
Here is the array I'm trying to work with:
let myNumbers = [4, 9, 6, 2, 3]
How can map this to the first and last of the sorted array to this?:
(2, 9)
Method 1: min()/max()
This is the easiest way:
let input = [4, 9, 6, 2, 3]
let output = (input.min(), input.max())
print(output) //(Optional(2), Optional(9))
If you're certain that the array isn't empty, you can safely force unwrap the optionals:
let input = [4, 9, 6, 2, 3]
let output = (input.min()!, input.max()!) // (2, 9)
This is approach does 2 iterations over the array. It's O(N). Unless a sorted list is required elsewhere, sorting then taking the first/last would be worse, as it would be O(N * log_2(N)).
Method 2: reduce()
If you insist on using reduce, you can do it like this:
let input = [4, 9, 6, 2, 3]
let output = input.reduce((min: Int.max, max: Int.min)){
(min($0.min, $1), max($0.max , $1))
} //(2, 9)
Each reduce iteration sets the accumulator to the new min (the smaller of the old min and current element), and the new max (the larger of the old max and the current).
The initial values of the accumulator are set such that:
Any element in the array compares as smaller than the accumulator's min
Any element in the array compares as larger than the accumulator's max
You don't need an initialValue for reduce, it's optional.
var foo = [1, 40, 20, -20, 50];
var reducer = function(prev, curr, i, arr){return [prev[0] <= curr ? prev[0] : curr, prev[1] >= curr ? prev[1] : curr]};
var baz = foo.reduce(reducer); // [-20, 50]
Or maybe like this:
var foo = [1, 40, 20, -20, 50];
var reducer = function(prev, curr, i, arr){return {min: prev.min <= curr ? prev.min : curr, max: prev.max >= curr ? prev.max : curr}};
var baz = foo.reduce(reducer); // {min: -20, max: 50}
Edit: Just noticed this is for swift and not javascript, whoops lol. I must have been surfing the wrong SO category. I think the principle would be the same in swift except you probably do need to provide some kind of initial value.

Append new variables to IDL for loop array

If I have the following array:
x = double([1, 1, 1, 10, 1, 1, 50, 1, 1, 1 ])
I want to do the following:
Group the array into groups of 5 which will each be evaluated separately.
Identify the MAX value each of the groups of the array
Remove that MAX value and put it into another array.
Finally, I want to print the updated array x without the MAX values, and the new array containing the MAX values.
How can I do this? I am new to IDL and have had no formal training in coding.
I understand that I can write the code to group and find the max values this way:
FOR i = 1, (n_elements(x)-4) do begin
print, "MAX of array", MAX( MAX(x[i-1:1+3])
ENDFOR
However, how do I implement all of what I specified above? I know I have to create an empty array that will append the values found by the for loop, but I don't know how to do that.
Thanks
I changed your x to have unique elements to make sure I wasn't fooling myself. It this, the number of elements of x must be divisible by group_size:
x = double([1, 2, 3, 10, 4, 5, 50, 6, 7, 8])
group_size = 5
maxes = max(reform(x, group_size, n_elements(x) / group_size), ind, dimension=1)
all = bytarr(n_elements(x))
all[ind] = 1
x_without_maxes = x[where(all eq 0)]
print, maxes
print, x_without_maxes
Lists are good for this, because they allow you to pop out values at specific indices, rather than rewriting the whole array again. You might try something like the following. I've used a while loop here, rather than a for loop, because it makes it a little easier in this case.
x = List(1, 1, 1, 10, 1, 1, 50, 1, 1, 1)
maxValues = List()
pos = 4
while (pos le x.length) do begin
maxValues.add, max(x[pos-4:pos].toArray(), iMax)
x.Remove, iMax+pos-4
pos += 5-1
endwhile
print, "Max Values : ", maxValues.toArray()
print, "Remaining Values : ", x.toArray()
This allows you to do what you want I think. At the end, you have a List object (which can easily be converted to an array) with the max values for each group of 5, and another containing the remaining values.
Also, please tag this as idl-programming-language rather than idl. They are two different tags.

Indexing 1d array with values in a 2d array

I have an array, tiles, which contains tiles in a tileset. I also have a 15x10 2 dimensional array, room, which has numbers corresponding to the tiles in tiles. What I'm having trouble with is this:
room = { ... } -- 15x10 2d array
csv = require("csv") -- load a csv file, not relevant to the problem
file = csv.open("room/room-0.0.csv")
row = 1
for fields in file:lines() do
for col, val in ipairs(fields) do
room[row][col] = val
end
row = row + 1
end
-- room looks something like this:
-- { {1, 4, 2, 3, 2, ...},
-- ...
-- {3, 3, 2, 4, 2, ...} }
All is well at this point. Here is where things go wrong though:
tiles = {"banana", "apple", "orange", "pitaya"}
for i, j in ipairs(room) do -- looping through room
print("-------")
for k, tilenum in ipairs(j) do -- tilenum = room[i][k]
print(tiles[tilenum]) -- tiles[room[k][i]]
end -- tiles[tilenum] == nil
end
The output:
-------
nil
nil
nil
nil
nil
...
What should happen:
-------
banana
pitaya
apple
orange
apple
...
Note: Though the objects actually in tiles are not printable, I have tried this example with numbers, strings, etc. They don't work.
You are not showing the value of tilenum, but I suspect that even if it's a number, it's in a string form, and when indexing Lua tables, "1" index is not the same as 1 index (and that's probably why your tiles[tilenum] returns nil).
You need to check the val values you assign (that later become tilenum) and if they are indeed numbers, then change = val to = tonumber(val).

Resources