Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays Scala逻辑索引,用于理解_Arrays_Matlab_Scala - Fatal编程技术网

Arrays Scala逻辑索引,用于理解

Arrays Scala逻辑索引,用于理解,arrays,matlab,scala,Arrays,Matlab,Scala,我试图将以下Matlab逻辑索引模式转换为Scala代码: % x is an [Nx1] array of Int32 % y is an [Nx1] array of Int32 % myExpensiveFunction() processes batches of unique x. ux = unique(x); z = nan(size(x)); for i = 1:length(ux) idx = x == ux(i); z(idx) = myExpensiveFunti

我试图将以下Matlab逻辑索引模式转换为Scala代码:

% x is an [Nx1] array of Int32
% y is an [Nx1] array of Int32
% myExpensiveFunction() processes batches of unique x.

ux = unique(x);
z = nan(size(x));
for i = 1:length(ux)
  idx = x == ux(i);
  z(idx) = myExpensiveFuntion(x(idx), y(idx));
end
假设我正在Scala中使用
valx:Array[Int]
。最好的方法是什么


编辑:为了澄清,我希望一次处理(x,y)批,按唯一的x分组,并返回一个结果(z),其顺序与初始输入相对应。我对排序x持开放态度,但最终需要回到原始的未排序顺序。我的主要要求是以一种清晰且合理有效的方式处理所有索引/映射/排序。

在Scala中,这大部分都非常简单;唯一有点与众不同的是独特的
x
索引。在Scala中,您可以使用“groupBy”来实现这一点。因为这是一个非常重索引的方法,我要放弃,一直使用索引:

val z = Array.fill(x.length)(Double.NaN)
x.indices.groupBy(i => x(i)).foreach{ case (xi, is) =>
  is.foreach(i => z(i) = myExpensiveFunction(xi, y(i)))
}
z
假设您可以生活在缺少向量的情况下,转到
myExpensiveFunction
。如果没有,

val z = Array.fill(x.length)(Double.NaN)
x.indices.groupBy(i => x(i)).foreach{ case (xi, is) =>
  val xs = Array.fill(is.length)(xi)
  val ys = is.map(i => y(i)).toArray
  val zs = myExpensiveFunction(xs, ys)
  is.foreach(i => z(i) = zs(i))
}
z
这不是在Scala中进行计算的最自然的方法,也不是最有效的方法,但是如果您的昂贵函数很昂贵,那么您就不关心效率了,这是我能找到的最接近直译的方法


(将你的matlab算法翻译成几乎所有的东西都需要一定程度的痛苦或反思,因为matlab中的“自然”计算与大多数其他语言中的计算不同。)

重要的一点是正确使用matlab的
独特的
。一个简单的解决方案是使用
集合
来确定唯一值:

val occurringValues = x.toSet

occurringValues.foreach{ value =>
  val indices = x.indices.filter(i => x(i) == value)
  for (i <- indices) {
    z(i) = myExpensiveFunction(x(i), y(i))
  }
}
val occurringValues=x.toSet
occurringValues.foreach{value=>
val index=x.index.filter(i=>x(i)==value)
对于(i
scala>def进程(xs:Array[Int],ys:Array[Int],f:(Seq[Int],Seq[Int])=>Double):Array[Double]={
|val ux=xs.distinct
|val zs=Array.fill(xs.size)(Double.NaN)
|对于(x x x(i)=x}
|val res=f(idx.map(xs),idx.map(ys))
|idx foreach{i=>zs(i)=res}
|   }
|zs
| }
进程:(xs:Array[Int],ys:Array[Int],f:(Seq[Int],Seq[Int])=>Double)数组[Double]
scala>valxs=Array(1,2,1,2,3)
xs:Array[Int]=数组(1,2,1,2,3)
scala>val ys=数组(1,2,3,4,5)
ys:Array[Int]=数组(1,2,3,4,5)
scala>valf=(a:Seq[Int],b:Seq[Int])=>a.sum/b.sum.toDouble
f:(序号[Int],序号[Int])=>Double=
scala>进程(xs、ys、f)
res0:Array[Double]=数组(0.5,0.6666,0.5,0.6666,0.6)

对于那些不懂MatLab的人,你能澄清一下你想做什么计算吗?IIRC:MatLab的
unique
返回
x
中的唯一值,该值在Scala中转换为
Set
。表达式
idx=x==ux(i)
给出了一个索引的布尔向量,它对应于某个唯一的值。
z
x
y
被投影/简化为这些索引。@RandallSchulz-Scala用户最奇怪的部分是,在matlab中,如果你用二进制向量对向量进行索引,它将使用它作为要使用哪些索引的过滤器。S非常简单,除非您可以分配到过滤器中。因此
z(a)=y(a)+1
z
的每个元素设置为等于
y
的相应元素加上一个元素索引,其中
a
为真(实际上,1)。听起来在Scala中实现一个类似MatLab的库/工具箱/框架会很有趣。谢谢Rex。你能用一种更具Scala风格/效率的方法来实现这一点吗?@chriswynyk-嗯,不,因为我不知道为什么我有一个昂贵的函数,它喜欢相同
x
值的向量和一堆不相同的
y
s,以及为什么答案需要与
y
s的原始顺序保持一致。@chriswynyk-我至少建议了每个元素
myExpensiveFunction
变量。
scala> def process(xs: Array[Int], ys: Array[Int], f: (Seq[Int], Seq[Int]) => Double): Array[Double] = {
     |   val ux = xs.distinct
     |   val zs = Array.fill(xs.size)(Double.NaN)
     |   for(x <- ux) {
     |     val idx = xs.indices.filter{ i => xs(i) == x }
     |     val res = f(idx.map(xs), idx.map(ys))
     |     idx foreach { i => zs(i) = res }
     |   }
     |   zs
     | }
process: (xs: Array[Int], ys: Array[Int], f: (Seq[Int], Seq[Int]) => Double)Array[Double]

scala> val xs = Array(1,2,1,2,3)
xs: Array[Int] = Array(1, 2, 1, 2, 3)

scala> val ys = Array(1,2,3,4,5)
ys: Array[Int] = Array(1, 2, 3, 4, 5)

scala> val f = (a: Seq[Int], b: Seq[Int]) => a.sum/b.sum.toDouble
f: (Seq[Int], Seq[Int]) => Double = <function2>

scala> process(xs, ys, f)
res0: Array[Double] = Array(0.5, 0.6666666666666666, 0.5, 0.6666666666666666, 0.6)