如果我想返回一个元素是 等于输入列表的相应元素乘以其在列表中的位置,我可以执行以下操作:
ML :: [Int] -> [Int]
ML [] = []
ML (x:xs) = x * x-1 : ML xs
但是我输入[6,3,5,1]
时得到的相应列表给出了[35,8,24,0]
的结果
有没有类似的方式我可以得到[0,3,10,3]
答案 0 :(得分:9)
是的,zipWith函数可以提供帮助:
ML :: [Int] -> Int -> [Int]
ML [] _ = []
ML (x:xs) n = x * n : ML xs n+1
返回zipWith (*) [0..] [6, 3, 5, 1]
当前代码不起作用,因为它只是在当前元素上调用[0, 3, 10, 3]
,但是zipWith是一个函数,它用索引列表(x * x - 1
等于zip [0..] [6, 3, 5, 1]
),然后评估传递的函数,该函数在每个元素上使用2个参数。类似于:
[(0, 6), (1, 3), (2, 5), (3, 1)]
因此,函数定义为:
map (uncurry (*)) $ zip [0..] [6, 3, 5, 1]
答案 1 :(得分:8)
您编写的代码(假设函数名称实际上是有效的函数名称,例如import { Component, OnInit} from '@angular/core';
import * as io from 'socket.io-client';
@Component({
selector: 'app-chatbox',
templateUrl: './chatbox.component.html',
styleUrls: ['./chatbox.component.css'],
})
export class ChatboxComponent implements OnInit {
socket;
messages: string[] = [];
constructor() { this.socket = io.connect('http://localhost:8000'); }
ngOnInit() {
this.initializeChatServer();
}
initializeChatServer() {
this.messages.push( 'test 55');//This line works
this.socket.on('newmessage', data => {
console.log('message -> ' + data.nick + '>' + data.msg);
this.messages.push(data.msg); //Cannot read property 'push' of undefined
});
}
}
)被解析为:
ml
这是因为ml :: [Int] -> [Int]
ml [] = []
ml (x:xs) = ((x * x)-1) : (ml xs)
比(*)
具有更高的固定性(优先级),而(+)
的固定性也高于(:)
,而功能应用程序ml xs
的固定性最高。 br />
也就是说,您正在将每个元素更改为其正方形,然后减去1。
现在您真正想要的是某种了解元素索引的方法。
这可以通过在递归中使用额外的参数来实现。
ml :: Int -> [Int] -> [Int]
ml _ [] = []
ml i (x:xs) = x*i : ml (i+1) xs
但是请注意,我们函数的签名已更改,我们现在接受一个额外的Int
参数,并且希望用户像ml 0 someList
一样调用,但是我们不想依赖用户传递有效数据,我们希望用户仅传递列表。因此,我们可以将此函数重命名为其他名称,例如ml_internal
并使用ml
作为正确的代码
ml :: [Int] -> [Int]
ml xs = ml_internal 0 xs
ml_internal :: Int -> [Int] -> [Int]
ml_internal _ [] = []
ml_internal i (x:xs) = x*i : ml_internal (i+1) xs
现在我们不想公开ml_internal
,我们可以通过将这段代码放在模块中并仅导出ml
来实现,但是没有理由这样做。我们也可能不希望ml_internal
可用于同一模块中的其他功能。因此,我们可以将ml_internal
放在where
的{{1}}子句中:
ml
现在,我们也可以省略ml :: [Int] -> [Int]
ml xs = ml_internal 0 xs
where
ml_internal :: Int -> [Int] -> [Int]
ml_internal _ [] = []
ml_internal i (x:xs) = x*i : ml_internal (i+1) xs
的类型签名,因为可以推断出它,并且在某些情况下,如果不启用称为ml_internal
的语言扩展,编译器就无法正确处理显式签名。
我们还可以将ScopedTypeVariables
重命名为ml_internal
,这是此类构造的广泛使用的名称,以获取go
的以下代码:
ml
答案 2 :(得分:4)
您实际上根本不需要查看索引即可解决此问题!试试这个实现:
ml :: Num a => [a] -> [a]
ml [] = []
ml (_:xs) = 0 : zipWith (+) xs (ml xs)
我们不是将第n个元素直接乘以n,而是安排将第n个元素的n个副本一次加在一起。肯定比使用显式乘法的迭代方法要慢,但是我认为它避免了一次索引就很有意义。
在实际代码中,我只会使用另一个答案中提出的zipWith (*)
实现。
答案 3 :(得分:1)
s.connect()
尝试使用此方法。将元素的索引作为另一个参数传递:)