公告:所有在
2025 年 4 月 15 日之前注册使用 Earth Engine 的非商业项目都必须
验证是否符合非商业性质的资格条件,才能继续使用 Earth Engine。
函数式编程概念
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
函数式编程简介
Earth Engine 使用并行处理系统在大量机器上执行计算。为了实现此类处理,Earth Engine 利用了函数式语言常用的标准技术,例如引用透明性和延迟评估,从而显著提高优化程度和效率。
使函数式编程与过程式编程区别开来的主要概念是没有副作用。这意味着,您编写的函数不依赖于函数外部的数据,也不会更新函数外部的数据。正如您将在下面的示例中看到的,您可以重新构建问题,以便使用无副作用的函数来解决问题,这些函数更适合并行执行。
For 循环
不建议在 Earth Engine 中使用 for 循环。您可以使用 map()
操作实现相同的结果,在该操作中,您可以指定一个可独立应用于每个元素的函数。这样,系统就可以将处理任务分配给不同的机器。
以下示例展示了如何使用 map()
获取数字列表,并创建包含每个数字的平方的另一个列表:
代码编辑器 (JavaScript)
// This generates a list of numbers from 1 to 10.
var myList = ee.List.sequence(1, 10);
// The map() operation takes a function that works on each element independently
// and returns a value. You define a function that can be applied to the input.
var computeSquares = function(number) {
// We define the operation using the EE API.
return ee.Number(number).pow(2);
};
// Apply your function to each item in the list by using the map() function.
var squares = myList.map(computeSquares);
print(squares); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
if/else 条件
习惯于过程式编程范式的新用户面临的另一个常见问题是如何在 Earth Engine 中正确使用 if/else 条件运算符。虽然该 API 确实提供了 ee.Algorithms.If()
算法,但我们强烈建议不要使用该算法,而应使用 map()
和过滤条件来采用更实用的方法。Earth Engine 使用
延迟执行,这意味着表达式的评估会延迟到实际需要其实现值时才进行。在某些情况下,这种执行模型会同时评估 ee.Algorithms.If()
语句的 true 和 false 分支。这可能会导致额外的计算和内存使用,具体取决于表达式以及执行这些表达式所需的资源。
假设您要解决上述示例的变体,其中任务是仅计算奇数的平方。下面展示了一种不使用 if/else 条件来解决此问题的函数式方法:
代码编辑器 (JavaScript)
// The following function determines if a number is even or odd. The mod(2)
// function returns 0 if the number is even and 1 if it is odd (the remainder
// after dividing by 2). The input is multiplied by this remainder so even
// numbers get set to 0 and odd numbers are left unchanged.
var getOddNumbers = function(number) {
number = ee.Number(number); // Cast the input to a Number so we can use mod.
var remainder = number.mod(2);
return number.multiply(remainder);
};
var newList = myList.map(getOddNumbers);
// Remove the 0 values.
var oddNumbers = newList.removeAll([0]);
var squares = oddNumbers.map(computeSquares);
print(squares); // [1, 9, 25, 49, 81]
这种范式尤其适用于处理集合。如果您想根据某些条件对集合应用不同的算法,首选方法是先根据条件过滤集合,然后对每个子集应用不同的函数。map()
这样,系统就可以并行执行操作。例如:
代码编辑器 (JavaScript)
// Import Landsat 8 TOA collection and filter to 2018 images.
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')
.filterDate('2018-01-01', '2019-01-01');
// Divide the collection into 2 subsets and apply a different algorithm on them.
var subset1 = collection.filter(ee.Filter.lt('SUN_ELEVATION', 40));
var subset2 = collection.filter(ee.Filter.gte('SUN_ELEVATION', 40));
// Multiply all images in subset1 collection by 2;
// do nothing to subset2 collection.
var processed1 = subset1.map(function(image) {
return image.multiply(2);
});
var processed2 = subset2;
// Merge the collections to get a single collection.
var final = processed1.merge(processed2);
print('Original collection size', collection.size());
print('Processed collection size', final.size());
累计迭代
您可能需要执行顺序操作,其中每次迭代的结果都会被后续迭代使用。Earth Engine 提供了 iterate()
方法来执行此类任务。请注意,iterate()
是按顺序执行的,因此对于大型操作来说会很慢。仅当您无法使用 map()
和过滤条件来实现所需输出时,才使用此函数。
iterate()
的一个很好的演示是创建 Fibonacci 数序列。在此示例中,序列中的每个数字都是前两个数字之和。iterate()
函数接受 2 个实参,即一个函数(算法)和一个起始值。该函数本身会传递 2 个值:迭代中的当前值和上一次迭代的结果。以下示例演示了如何在 Earth Engine 中实现斐波那契数列。
代码编辑器 (JavaScript)
var algorithm = function(current, previous) {
previous = ee.List(previous);
var n1 = ee.Number(previous.get(-1));
var n2 = ee.Number(previous.get(-2));
return previous.add(n1.add(n2));
};
// Compute 10 iterations.
var numIteration = ee.List.repeat(1, 10);
var start = [0, 1];
var sequence = numIteration.iterate(algorithm, start);
print(sequence); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
现在,您已经对 JavaScript 概念有了很好的了解,可以参阅 API 教程,了解 Earth Engine API 的地理空间功能。
如未另行说明,那么本页面中的内容已根据知识共享署名 4.0 许可获得了许可,并且代码示例已根据 Apache 2.0 许可获得了许可。有关详情,请参阅 Google 开发者网站政策。Java 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-26。
[null,null,["最后更新时间 (UTC):2025-07-26。"],[[["\u003cp\u003eEarth Engine leverages functional programming principles, like referential transparency and lazy evaluation, for parallel processing and optimization.\u003c/p\u003e\n"],["\u003cp\u003eAvoid for-loops and if/else statements; utilize \u003ccode\u003emap()\u003c/code\u003e for parallel processing and filters for conditional operations on collections.\u003c/p\u003e\n"],["\u003cp\u003eUse \u003ccode\u003eiterate()\u003c/code\u003e for cumulative, sequential operations where each step depends on the previous, but note its potential performance limitations.\u003c/p\u003e\n"],["\u003cp\u003eFunctional programming in Earth Engine prioritizes side-effect-free functions for efficient distributed computation across its infrastructure.\u003c/p\u003e\n"],["\u003cp\u003eEarth Engine's deferred execution model impacts how \u003ccode\u003eee.Algorithms.If()\u003c/code\u003e statements are evaluated, potentially leading to unnecessary computations.\u003c/p\u003e\n"]]],[],null,["# Functional Programming Concepts\n\nIntroduction to functional programming\n--------------------------------------\n\nEarth Engine uses a parallel processing system to carry out computation across a large number of\nmachines. To enable such processing, Earth Engine takes advantage of standard techniques commonly\nused by functional languages, such as referential transparency and lazy evaluation, for significant\noptimization and efficiency gains.\n\nThe main concept that sets functional programming apart from procedural programming is *the\nabsence of side effects*. What it means is that the functions that you write doesn't rely on or\nupdate data that is outside of the function. As you will see in the examples below, it is possible\nto re-structure your problem so that it can be solved using functions without side-effects - which\nare much better suited to be executed in parallel.\n\n### For Loops\n\nThe use of for-loops is discouraged in Earth Engine. The same results can be achieved using a\n`map()` operation where you specify a function that\ncan be independently applied to each element. This allows the system to distribute the processing to\ndifferent machines.\n\nThe example below illustrates how you would take a list of numbers and create another list with\nthe squares of each number using `map()`:\n\n\n### Code Editor (JavaScript)\n\n```javascript\n// This generates a list of numbers from 1 to 10.\nvar myList = ee.List.sequence(1, 10);\n\n// The map() operation takes a function that works on each element independently\n// and returns a value. You define a function that can be applied to the input.\nvar computeSquares = function(number) {\n // We define the operation using the EE API.\n return ee.Number(number).pow(2);\n};\n\n// Apply your function to each item in the list by using the map() function.\nvar squares = myList.map(computeSquares);\nprint(squares); // [1, 4, 9, 16, 25, 36, 49, 64, 81]\n```\n\n### If/Else Conditions\n\nAnother common problem faced by new users who are used to procedural\nprogramming paradigm is the proper use of if/else conditional operators in Earth Engine. While, the API\ndoes provide a `ee.Algorithms.If()` algorithm, the use of it is strongly discouraged\nin favor of a more functional approach using `map()` and filters.\nEarth Engine uses [deferred execution](/earth-engine/guides/deferred_execution), which means that the evaluation of an expression is delayed until its\nrealized value is actually required. In some cases, this type of execution model will evaluate\nboth the true and false alternatives of an `ee.Algorithms.If()` statement. This can\nlead to extra computation and memory usage, depending on the expressions and the resources\nrequired to execute them.\n\nSay you want to solve a variant of the above example, where the task is to compute squares of\nonly odd numbers. A functional approach to solving this without if/else conditions, is demonstrated\nbelow:\n\n### Code Editor (JavaScript)\n\n```javascript\n// The following function determines if a number is even or odd. The mod(2)\n// function returns 0 if the number is even and 1 if it is odd (the remainder\n// after dividing by 2). The input is multiplied by this remainder so even\n// numbers get set to 0 and odd numbers are left unchanged.\nvar getOddNumbers = function(number) {\n number = ee.Number(number); // Cast the input to a Number so we can use mod.\n var remainder = number.mod(2);\n return number.multiply(remainder);\n};\n\nvar newList = myList.map(getOddNumbers);\n\n// Remove the 0 values.\nvar oddNumbers = newList.removeAll([0]);\n\nvar squares = oddNumbers.map(computeSquares);\nprint(squares); // [1, 9, 25, 49, 81]\n```\n\nThis paradigm is especially applicable when working with collections. If you wanted to apply\na different algorithm to the collection based on some conditions, the preferred way is to first\nfilter the collection based on the condition, and then `map()` a different function to\neach of the subsets. This allows the system to parallelize the operation. For example:\n\n\n### Code Editor (JavaScript)\n\n```javascript\n// Import Landsat 8 TOA collection and filter to 2018 images.\nvar collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_TOA')\n .filterDate('2018-01-01', '2019-01-01');\n\n// Divide the collection into 2 subsets and apply a different algorithm on them.\nvar subset1 = collection.filter(ee.Filter.lt('SUN_ELEVATION', 40));\nvar subset2 = collection.filter(ee.Filter.gte('SUN_ELEVATION', 40));\n\n// Multiply all images in subset1 collection by 2;\n// do nothing to subset2 collection.\nvar processed1 = subset1.map(function(image) {\n return image.multiply(2);\n});\nvar processed2 = subset2;\n\n// Merge the collections to get a single collection.\nvar final = processed1.merge(processed2);\nprint('Original collection size', collection.size());\nprint('Processed collection size', final.size());\n```\n\n### Cumulative Iteration\n\nYou may need to do sequential operation, where the result of\neach iteration is used by the subsequent iteration. Earth Engine provides a `iterate()`\nmethod for such tasks. Remember that `iterate()` is executed in a sequential manner and\nhence will be slow for large operations. Use it only when you are not able to use `map()`\nand filters to achieve the desired output.\n\nA good demonstration of `iterate()` is for creation of [Fibonacci number](https://en.wikipedia.org/wiki/Fibonacci_number) sequence. Here, each\nnumber in the series is the sum of previous 2 numbers. The `iterate()` function takes 2\narguments, a function (algorithm) and a starting value. The function itself gets passed on 2 values,\nthe current value in the iteration, and the result of the previous iteration. The following example\ndemonstrates how to implement a fibonacci sequence in Earth Engine.\n\n### Code Editor (JavaScript)\n\n```javascript\nvar algorithm = function(current, previous) {\n previous = ee.List(previous);\n var n1 = ee.Number(previous.get(-1));\n var n2 = ee.Number(previous.get(-2));\n return previous.add(n1.add(n2));\n};\n\n// Compute 10 iterations.\nvar numIteration = ee.List.repeat(1, 10);\nvar start = [0, 1];\nvar sequence = numIteration.iterate(algorithm, start);\nprint(sequence); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]\n```\n\nNow that you have a good understanding of javascript concepts, you can see the [API Tutorial](/earth-engine/tutorials/tutorial_api_01) for an introduction to the geospatial functionality of the\nEarth Engine API."]]