if 里面嵌套for,能优化一下代码吗?

g
gooog
楼主 (北美华人网)
#定义if的条件变量shuffle shuffle = true # shuffle = false
if(shuffle) { 口口g = 100; 口口m = 2; 口口blocks; # 这段代码输出是b,输入是x 口口for(int i=0; i< m; i++){ 口口口口a = f1(b) + g; 口口} } else { 口口g= 200; 口口m = 3; 口口blocks; # 这段代码输出是b,输入是x,与上面那个无论是输入还是输出的数值都是一模一样的。 口口for(int i=0; i< m; i++){ 口口口口a = f2(b) + g; 口口} }
请问这段代码还能优化吗?
因为这个blocks非常长,大概1万行。而这个是完全一模一样的。大家怎么处理这段代码? 1) 把blocks变成一个函数。这个方法好吗? 2) 有啥办法让blocks代码只写一次,然后把if嵌入到for里面去? 3) 其他方法
类似上面这段代码,在编程的时候,有大量行的blocks是一模一样的。大家有不写成函数的时候吗?比如:输入参数太多了。输出参数多且类型也多。比如1000个输入参数,100个不同维数的矩阵输出。 不写成函数,但是重复代码,有什么利?有什么不利? 会影响程序的运行速度吗?(好像还会比写成函数运算快一些。对吧。) 会占用更多的内存吗?
###########问题2 请问如何动态实现for循环嵌入的层数 比如如果m=3 就是 for(i3 in 1:k){ for(i2 in 1:k) { for(i1 in 1:k) {  out <- c(i1, i2, i3)  print(out) } } }
如果m=2 for(i2 in 1:k) { for(i1 in 1:k) {  out <- c(i1, i2)  print(out) } }
如果m=1
for(i1 in 1:k) {  out <- c(i1)  print(out) }





d
dustflying
#定义if的条件变量shuffle shuffle = true # shuffle = false
if(shuffle) { 口口g = 100; 口口m = 2; 口口blocks; # 这段代码输出是b,输入是x 口口for(int i=0; i< m; i++){ 口口口口a = f(b) + g; 口口} } else { 口口g= 200; 口口m = 3; 口口blocks; # 这段代码输出是b,输入是x,与上面那个无论是输入还是输出的数值都是一模一样的。 口口for(int i=0; i< m; i++){ 口口口口a = f(b) + g; 口口} }
请问这段代码还能优化吗?
因为这个blocks非常长,大概1万行。而这个是完全一模一样的。大家怎么处理这段代码? 1) 把blocks变成一个函数。这个方法好吗? 2) 有啥办法让blocks代码只写一次,然后把if嵌入到for里面去? 3) 其他方法


gooog 发表于 2023-09-14 10:29

你是新手吗?
为什么不写成这样:
if(shuffle) { 口口g = 100; 口口m = 2;
} else { 口口g= 200; 口口m = 3;
}
口口blocks; # 这段代码输出是b,输入是x,与上面那个无论是输入还是输出的数值都是一模一样的。 口口for(int i=0; i< m; i++){ 口口口口a = f(b) + g; 口口}
x
xcosmos
#定义if的条件变量shuffle shuffle = true # shuffle = false
if(shuffle) { 口口g = 100; 口口m = 2; 口口blocks; # 这段代码输出是b,输入是x 口口for(int i=0; i< m; i++){ 口口口口a = f(b) + g; 口口} } else { 口口g= 200; 口口m = 3; 口口blocks; # 这段代码输出是b,输入是x,与上面那个无论是输入还是输出的数值都是一模一样的。 口口for(int i=0; i< m; i++){ 口口口口a = f(b) + g; 口口} }
请问这段代码还能优化吗?
因为这个blocks非常长,大概1万行。而这个是完全一模一样的。大家怎么处理这段代码? 1) 把blocks变成一个函数。这个方法好吗? 2) 有啥办法让blocks代码只写一次,然后把if嵌入到for里面去? 3) 其他方法


gooog 发表于 2023-09-14 10:29

可以把blocks弄成一个函数 在进入if statement之前算一次就好了 f(b)也可以只算一次在if 之前只算一次
x
xcosmos
可以把blocks弄成一个函数 在进入if statement之前算一次就好了 f(b)也可以只算一次在if 之前只算一次
xcosmos 发表于 2023-09-14 10:39

就是 b=blocks(x) new variable=f(b) if(shuffle){ for loop } else{ for loop }
g
gooog
你是新手吗?
为什么不写成这样:
if(shuffle) { 口口g = 100; 口口m = 2;
} else { 口口g= 200; 口口m = 3;
}
口口blocks; # 这段代码输出是b,输入是x,与上面那个无论是输入还是输出的数值都是一模一样的。 口口for(int i=0; i< m; i++){ 口口口口a = f(b) + g; 口口}
dustflying 发表于 2023-09-14 10:38

不好意思。for循环里的f(b)在条件if下,一个是f1,一个是f2,它们有些细微的区别。
一生所爱
回复 1楼gooog的帖子
for loop 跟if 没有任何关系啊,为啥要写在if里面? if 只管赋值就好
w
wantU
chatgpt一下
n
nickbear
不好意思。for循环里的f(b)在条件if下,一个是f1,一个是f2,它们有些细微的区别。
gooog 发表于 2023-09-14 10:53

那就修改f1,f2成一样的,或者加parameter控制行为 软件可复用的基本原则就是模块化和consolidate重复逻辑
p
pineappletin
我觉得当年我果断放弃编程是正确的…
g
gooog
那就修改f1,f2成一样的,或者加parameter控制行为 软件可复用的基本原则就是模块化和consolidate重复逻辑
nickbear 发表于 2023-09-14 10:59

f1,f2不能改成一样的。受shuffle这个参数控制。
g
gokgs
g = shuffle ? 100 : 200; m = shuffle ? 2 : 3; blocks; for(int i=0; i< m; i++){ tmp = shuffle ? f1(b) : f2(b); a = tmp + g; }
马工的脸都让你们给丢尽了。
x
xcosmos
不好意思。for循环里的f(b)在条件if下,一个是f1,一个是f2,它们有些细微的区别。
gooog 发表于 2023-09-14 10:53

那就只把blocks放到if之前就好了
v
verayao
把for loop写成function take 你的各种变量 b x f 就不用重复了 我刚开始写代码的时候mentor说 never repeat yourself
n
nickbear
f1,f2不能改成一样的。受shuffle这个参数控制。
gooog 发表于 2023-09-14 11:02

这就是我说的“增加parameter控制行为” 函数体可以一样,input parameter value不一样
d
dustflying
g = shuffle ? 100 : 200; m = shuffle ? 2 : 3; blocks; for(int i=0; i< m; i++){ tmp = shuffle ? f1(b) : f2(b); a = tmp + g; }
马工的脸都让你们给丢尽了。
gokgs 发表于 2023-09-14 11:02

哈哈,我可不是马工。
你可还可以减少计算:
g = shuffle ? 100 : 200; m = shuffle ? 2 : 3; blocks; tmp = shuffle ? f1(b) : f2(b); for(int i=0; i< m; i++){
a = tmp + g; }
g
gooog
那就修改f1,f2成一样的,或者加parameter控制行为 软件可复用的基本原则就是模块化和consolidate重复逻辑
nickbear 发表于 2023-09-14 10:59

请问python里面的参数不同,那么函数就不同。这个怎么实现的?
比如: ml = LinearRegression() model = ml.fit(X_train, y_train) y_prediction = model.predict(X_train)
#### ml = DecisionTreeClassifier() model = ml.fit(X_train, y_train) y_prediction = model.predict(X_train)
这个只需要改第一行,而后面的行都不用更改。这是怎么实现的? 用R怎么能实现这个呢?
这个技术和函数比较起来,有什么优点和缺点吗?
g
gooog
g = shuffle ? 100 : 200; m = shuffle ? 2 : 3; blocks; for(int i=0; i< m; i++){ tmp = shuffle ? f1(b) : f2(b); a = tmp + g; }
马工的脸都让你们给丢尽了。
gokgs 发表于 2023-09-14 11:02

理论上讲。你这个代码的速度要慢一些。 因为如果这个m是个巨大值的话,比如m=1e5, 那么你就要多出来很多条件判断 tmp = shuffle ? f1(b) : f2(b);
这是不是就是把if移到for里面去的弊病?
我就是基于这个考虑,才把if放到for的外面 (for循环在if的里面)
x
xcosmos
请问python里面的参数不同,那么函数就不同。这个怎么实现的?
比如: ml = LinearRegression() model = ml.fit(X_train, y_train) y_prediction = model.predict(X_train)
#### ml = DecisionTreeClassifier() model = ml.fit(X_train, y_train) y_prediction = model.predict(X_train)
这个只需要改第一行,而后面的行都不用更改。这是怎么实现的? 用R怎么能实现这个呢?
这个技术和函数比较起来,有什么优点和缺点吗?
gooog 发表于 2023-09-14 11:11

你查python polymorphism
g
gooog
把for loop写成function take 你的各种变量 b x f 就不用重复了 我刚开始写代码的时候mentor说 never repeat yourself
verayao 发表于 2023-09-14 11:04

但是如果代码重复的话,程序的速度会提速。 虽然编程的人会比较辛苦。因为如果这段代码要修改的话,你要修改很多重复的地方。
x
xcosmos
但是如果代码重复的话,程序的速度会提速。 虽然编程的人会比较辛苦。因为如果这段代码要修改的话,你要修改很多重复的地方。
gooog 发表于 2023-09-14 11:17

为什么“如果代码重复的话,程序的速度会提速。”?
n
nickbear
请问python里面的参数不同,那么函数就不同。这个怎么实现的?
比如: ml = LinearRegression() model = ml.fit(X_train, y_train) y_prediction = model.predict(X_train)
#### ml = DecisionTreeClassifier() model = ml.fit(X_train, y_train) y_prediction = model.predict(X_train)
这个只需要改第一行,而后面的行都不用更改。这是怎么实现的? 用R怎么能实现这个呢?
这个技术和函数比较起来,有什么优点和缺点吗?
gooog 发表于 2023-09-14 11:11

这是OOP的简单用法 在这个例子里面,LinearRegression和DecisionTree应该都是sk-learn里面Classifier类的子类 都实现了fit方法,所以你可以换一个classifier直接用 R我不熟,但是它也是支持OOP的
g
gooog
这是OOP的简单用法 在这个例子里面,LinearRegression和DecisionTree应该都是sk-learn里面Classifier类的子类 都实现了fit方法,所以你可以换一个classifier直接用 R我不熟,但是它也是支持OOP的
nickbear 发表于 2023-09-14 11:22

请问类的速度和函数比起来,快还是慢?
比如: class shape { int area(); };
shape triangle, square, rectangle, circle; triangle.area() square.area() rectangle.area() circle.area()
我们也可以用四个函数来完成 triangle_area() square_area() rectangle_area() circle_area()
假如我们需要对每个形状进行一亿次的运算。那么是用类来写的程序快,还是用函数来写的程序快呢? 简单的说,是fortran快,还是c++里的类编程,完成这个任务快? note:1亿次运算。


g
gokgs
请问类的速度和函数比起来,快还是慢?
比如: class shape { int area(); };
shape triangle, square, rectangle, circle; triangle.area() square.area() rectangle.area() circle.area()
我们也可以用四个函数来完成 triangle_area() square_area() rectangle_area() circle_area()
假如我们需要对每个形状进行一亿次的运算。那么是用类来写的程序快,还是用函数来写的程序快呢? 简单的说,是fortran快,还是c++里的类编程,完成这个任务快? note:1亿次运算。



gooog 发表于 2023-09-14 11:30

virtual function 当然有overhead, extra pointer dereference, 对大多数情况都是可以忽略不计的。
l
lee_hr
最好的办法是把block做成一个函数.
def fun(x): ##code ##return b. 然后原代码写成:
b = fun(x) if shuffle: ##g = 100 ##m = 2 ##for (......) ####a = f1(b) + g else: ##g=200 ##m=3 ##for(....) ####a = f2(b) + g ========================================================= 如果block需要g和m当参数的话:
def fun(x,g,m): ##code ##return b.
原函数可以写两次if,例如: g = 0 m = 0 if shuffle: ##g = 100 ##m = 2 else: ##g = 200 ##m = 3
b = fun(x, g, m)
if shuffle: ## for(....) #### a = f1(b) + g else ## for (...) #### a = f2(b) + g
n
nickbear
请问类的速度和函数比起来,快还是慢?
比如: class shape { int area(); };
shape triangle, square, rectangle, circle; triangle.area() square.area() rectangle.area() circle.area()
我们也可以用四个函数来完成 triangle_area() square_area() rectangle_area() circle_area()
假如我们需要对每个形状进行一亿次的运算。那么是用类来写的程序快,还是用函数来写的程序快呢? 简单的说,是fortran快,还是c++里的类编程,完成这个任务快? note:1亿次运算。



gooog 发表于 2023-09-14 11:30

你怎么一会Python,R一会儿Fortran,C++的 不同的语言生态和应用场合不一样,用Python/R的场合大概率不会用到Fortran/C++ 就这个问题来说,对同一种语言来说,类方法的速度没有明显区别 Fortran在一部分benchmark里速度是优于C++,但是数据分析场合用不上,对performance有需求应该上相应的高度优化的库和平台,而不是自己reinvent the wheel



l
lee_hr
至于什么‘直接写代码会不会比调用一个函数效率高’之类的问题,百分之九十九点九的情况下没有实际意义。特别对于新手程序员来说,根本不需要关注 ‘什么样的写法理论上有一点微小的效率提升’ (当然,把O(NlogN)能解决的问题写成O(N^3)另说)
第一,调用函数的开销很小。而且编译器完全有可能把这两种情况优化成同样的执行效率。 第二,如果是什么特殊用途,真的需要微小的效率提升,有很多种其他手段可以用于优化效率(比如选用更快的语言,如C/C++/汇编而非python,花钱上更快的机器,开各种编译器优化选项等等),而懂那些的人也自然会懂什么时候该用函数什么时候该不用,反正不是初级程序员需要操心的事情。 第三,也是最重要的一点,实践证明,程序员的时间,比机器时间重要。所以你优化代码的方向,应该是 便于维护,便于扩展,便于人类理解。写一个函数封装block的逻辑,把block和原主函数分开来,以后需要修改block内容时只用改一次。其他人需要看你代码时能便于理解。这些便利性远远比那不知道存在与否的一点效率提升重要的多得多得多。
g
gooog
多谢!
请问如何实现动态for循环嵌入的层数?
比如m=3,就嵌套3层循环, m=2,就嵌套2层循环 这个m是动态的。
m
mimikiki
最好的办法是把block做成一个函数.
def fun(x): ##code ##return b. 然后原代码写成:
b = fun(x) if shuffle: ##g = 100 ##m = 2 ##for (......) ####a = f1(b) + g else: ##g=200 ##m=3 ##for(....) ####a = f2(b) + g ========================================================= 如果block需要g和m当参数的话:
def fun(x,g,m): ##code ##return b.
原函数可以写两次if,例如: g = 0 m = 0 if shuffle: ##g = 100 ##m = 2 else: ##g = 200 ##m = 3
b = fun(x, g, m)
if shuffle: ## for(....) #### a = f1(b) + g else ## for (...) #### a = f2(b) + g
lee_hr 发表于 2023-09-14 11:46

Re一下,还可以略改进一下,其中for循环只写一遍,设一个函数指针*f (Java里用Interface)
if shuffle: ## f=f1 else ## f=f2
## for (...) #### a = f(b) + g
千渔千寻
回复 1楼的帖子
m大的话 loop unrolling
l
lee_hr
楼主你问的问题好脱离实际啊,你真的是程序员吗?什么样的用途需要你动态嵌套循环层数?如果你嵌套个6层,每层里循环20次,每次运算花1ms的话,哪怕没有其他任何overhead,一次执行要算0.74天。
要实现动态嵌套,最简单的办法就是递归。
n = 5 ##嵌套层数 m = 10 ##每层里循环次数
def fun(int n, int m) ##int result = 0 ##if (n < 1): #### Illegal variable, throw an error ##else if (n == 1): ##最后一层 #### for (int i = 0; i < m; i++) ###### result += constant ##else if (n > 1): #### for (int i = 0; i < m; i++) ###### result += fun (n-1, m) ##return result
l
lee_hr
Re一下,还可以略改进一下,其中for循环只写一遍,设一个函数指针*f (Java里用Interface)
if shuffle: ## f=f1 else ## f=f2
## for (...) #### a = f(b) + g

mimikiki 发表于 2023-09-14 13:06

你说得对,你要给我code review的话我会按这个改的,而且视情况可能会把那几个循环变量(g/m)写成三目运算也说不定,不过根据LZ主帖里反应的水平,我打算尽可能简单的来,就是直接if elif else写,唯一优化就是说服楼主把block写成函数(一万行的代码还打算重复两次!如果我自己上手的话这至少得break成十个以上的函数,可能好几个类库,每个函数之前至少加十行注释说明这个函数到底要干什么,我不相信LZ或者绝大多数程序员能够manage一万行的单个代码块函数),不加更多复杂写法
千渔千寻
回复 16楼gooog的帖子
动态绑定。和c语言里面的函数指针类似。其实就是指向内存中某个函数的首地址。是什么函数执行什么函数。
和宋朝差不多,做到将不知兵,兵不知将。打仗的时候再把将领分配给某支军队。