How do I sort a multidimensional table in Lua? - arrays

I have a table consisting basically of the following:
myTable = {{1, 6.345}, {2, 3.678}, {3, 4.890}}
and I'd like to sort the table by the decimal values.
So I'd like to the output to be:
{{2, 3.678}, {3, 4.890}, {1, 6.345}}
If possible, I'd like to use the table.sort() function. Thankyou in advance for the help :-)

Given that your table is a sequence, you can use table.sort directly. This function accepts a comparison predicate as its second argument, which prescribes the comparison logic:
require 'table'
myTable = {{1, 6.345}, {2, 3.678}, {3, 4.890}}
table.sort(myTable, function(lhs, rhs) return lhs[2] < rhs[2] end)
Printing the table e.g. as for _, v in ipairs(myTable) do print(v[1], v[2]) end then shows the desired ordering:
2 3.678
3 4.89
1 6.345
They key here is not the dimension of the table to sort, but the fact that it is a sequence, i.e. ordered.

Related

Why does set.average return a different value than array.average?

I was tinkering around with my IDE and I stumbled across something interesting. Check out this code:
val arr1 = intArrayOf(3, 3, 2)
val set1 = setOf(3, 3, 2)
println(arr1.average())
println(set1.average())
These appear pretty similar, but it returns this:
2.6666666666666665
2.5
Why are these returning different values?
From kotlinlang.org:
[A set is] A generic unordered collection of elements that does not support duplicate elements.
This means that even though you're initializing a set as {3, 3, 2}, it's actually {3, 2}. The average of {3, 2} is 2.5.

Array difference in postgresql

I have two arrays [1,2,3,4,7,6] and [2,3,7] in PostgreSQL which may have common elements. What I am trying to do is to exclude from the first array all the elements that are present in the second.
So far I have achieved the following:
SELECT array
(SELECT unnest(array[1, 2, 3, 4, 7, 6])
EXCEPT SELECT unnest(array[2, 3, 7]));
However, the ordering is not correct as the result is {4,6,1} instead of the desired {1,4,6}.
How can I fix this ?
I finally created a custom function with the following definition (taken from here) which resolved my issue:
create or replace function array_diff(array1 anyarray, array2 anyarray)
returns anyarray language sql immutable as $$
select coalesce(array_agg(elem), '{}')
from unnest(array1) elem
where elem <> all(array2)
$$;
I would use ORDINALITY option of UNNEST and put an ORDER BY in the array_agg function while converting it back to array. NOT EXISTS is preferred over except to make it simpler.
SELECT array_agg(e order by id)
FROM unnest( array[1, 2, 3, 4, 7, 6] ) with ordinality as s1(e,id)
WHERE not exists
(
SELECT 1 FROM unnest(array[2, 3, 7]) as s2(e)
where s2.e = s1.e
)
DEMO
More simple, NULL support, probably faster:
select array(
select v
from unnest(array[2,2,null,1,3,3,4,5,null]) with ordinality as t(v, pos)
where array_position(array[3,3,5,5], v) is null
order by pos
);
Result: {2,2,null,1,4,null}
Function array_diff() with tests.
Postgres is unfortunately lacking this functionality. In my case, what I really needed to do was to detect cases where the array difference was not empty. In that specific case you can do that with the #> operator which means "Does the first array contain the second?"
ARRAY[1,4,3] #> ARRAY[3,1,3] → t
See doc

How to check if an array is in a multidimensional array

I'd want to check, using a filtering query, if an array is equal to an element of another multidimensional array which can be considered as an array of arrays.
For example:
Given the multidimensional array {{1,2}, {3,4}, {5,6}} I want to check if a one dimension array of one of the array elements.
Expected results:
Input: {1,2} or {3,4} -> Output: TRUE
Input: {2,3} or {1,5} -> Output: FALSE
I've already tried <#, but it returns TRUE for all the examples cases and I can't use ANY without slicing the multidimensional array.
Does anyone have a solution without using pgplsql?
This does seem like a difficult problem to solve without any pgpsql. However, if this function is utilized, it is much simpler:
https://wiki.postgresql.org/wiki/Unnest_multidimensional_array
CREATE OR REPLACE FUNCTION public.reduce_dim(anyarray)
RETURNS SETOF anyarray AS
$function$
DECLARE
s $1%TYPE;
BEGIN
FOREACH s SLICE 1 IN ARRAY $1 LOOP
RETURN NEXT s;
END LOOP;
RETURN;
END;
$function$
LANGUAGE plpgsql IMMUTABLE;
To use:
create table array_test (arr integer[][]);
insert into array_test (select '{{1,2}, {3,4}, {5,6}}');
select (case when '{1,2}' in (select reduce_dim(arr) from array_test) then true
else false end);
case
------
t
(1 row)
select (case when '{1,4}' in (select reduce_dim(arr) from array_test) then true
else false end);
case
------
f
(1 row)
Simple way: search in array like in string:
select '{{1, 2}, {3, 4}, {5, 6}}'::int[][]::text like '%{1,2}%';
Complex way: decompose array to slices (without plpgsql):
with t(x) as (values('{{1, 2}, {3, 4}, {5, 6}}'::int[][]))
select *
from t
where (
select bool_or(x[s:s] = '{{1,3}}') from generate_subscripts(x,1) as s);

Splice Array in Postgres

Is it possible to (easily) splice arrays in Postgres? For example, I want to replace all values of 4 with the values 8 and 12, so an array of {2, 4, 7} should become {2, 8, 12, 7}. Perhaps I'm going about this the wrong way, but I need to maintain the integer array column type for these columns. Thanks for any guidance you can give me.
Perhaps UNNEST?
WITH rep(ord, what, with_what) AS(
VALUES (1,4,8),
(2,4,12)
)
SELECT array_agg(COALESCE(with_what,elem) ORDER BY no, ord) AS new_array
FROM(
SELECT *
FROM UNNEST('{2, 4, 7}'::INTEGER[]) WITH ORDINALITY AS arr(elem, no)
LEFT JOIN rep ON arr.elem = rep.what
) AS q;
This way you can define a whole set of replaces easily.

Populating array in mathematica

I have a set of around 500 (x,y,z) real values. Since I will need to bin the values based on their (x,y) coordinates, I stripped the z values and stored in on a seperate list. I am left with only the x,y values; I rescaled and rounded them to index pairs in the range of, 1..100 range.
Now I want to populate an array with the z values in a 100x100 matrix at the particular (x,y) coordinates.
More precisely,
I have a set of values for example : data = {{2.62399, 0.338057, 2.09629}, {1.8424, 0.135817, 3.21925}, {0.702257, 1.14502, 3.9335}...
I stripped it of its zvalues and store it in zvalues list:
zvalues = {2.09629, 3.21925, 3.9335....
I rounded, rescaled and created a new array of indices
indices = {{53, 7}, {37, 3}, {14, 23}...
I want to create a new 100x100 matrix and place the zvalues on the coordinates corresponding to the indices matrix
For example, in pseudocode
For (int i = 1, i < 101, i++){
NewArray(indices[i]) = zvalues[i];
}
The first time the loop will run, it should do NewArray(53,7) = 2.09629.
I want to know the syntax to loop through the indices array and populate the 2 dimensional 100x100 NewArray with zvalues
to follow your basic approach you need to initialize the array:
newArray=Table[,{100},{100}]
then in the loop the syntax is:
newArray[[indices[[i,1]],indices[[i,2]]]]=zdata[[i]]
note the double square brackets for referencing parts of arrays (or lists in Mathematica terminology)
A better approach would be to create a SparseArray, which for one thing would not require pre-initialization, or even knowing the dimensions in advance.
Finally in mathematica you can usually use an object oriented approach, avioding the "do" loop all together:
data = {{1.5, 1.1, 1.1}, {2.2, 2.2, 2.2}, {1.01, 2.3, 1.2}};
m1 = Table[, {2}, {2}];
(m1[[Floor[#[[1]]], Floor[#[[2]]]]] = #[[3]]) & /# data;
m1
m2 = SparseArray[ Floor[#[[1 ;; 2]]] -> #[[3]] & /# data , Automatic,];
Normal[m2]
{{1.1, 1.2}, {Null, 2.2}}
{{1.1, 1.2}, {Null, 2.2}}
While I don't understand why you want to create a new way of indexing your array, this will do what you want :
data = {{2.62399, 0.338057, 2.09629}, {1.8424, 0.135817, 3.21925}, {0.702257, 1.14502, 3.9335}};
zvalues = {2.09629, 3.21925, 3.9335};
indices = {{53, 7}, {37, 3}, {14, 23}};
newArray[xIndex_, yIndex_]:=Take[data, Position[indices, {xIndex, yIndex}][[1, 1]]][[1, 3]]
newArray[53, 7]
(* 2.09629 *)

Resources