このトピックでは、Java ユーザー定義関数 (UDF) または Python UDF を使用して、デリミタのないキーと値のペアの文字列から特定のキーの値を取得する方法について説明します。
説明
この例では、UDF_EXTRACT_KEY_VALUE という名前の UDF を作成します。
構文:
STRING UDF_EXTRACT_KEY_VALUE(STRING <s>, STRING <split1>, STRING <split2>, STRING <keyname>)
説明:
split1 を使用して文字列 s をキーと値のペアに分割し、split2 を使用してキーと値のペアをキーと値に分割し、keyname で指定されたキーの値を取得します。
説明この UDF は、デリミタを含む文字列には適していません。デリミタを含む文字列で特定のキーの値を取得する方法の詳細については、「例: デリミタのある文字列の値を取得する」をご参照ください。
パラメータ:
s: ソース文字列。このパラメータの値は STRING データ型です。このパラメータは必須です。
split1: キーと値のペアを取得するために使用する文字列デリミタ。このパラメータの値は STRING データ型です。このパラメータは必須です。
split2: キーと値を取得するために使用するキーと値のデリミタ。このパラメータの値は STRING データ型です。このパラメータは必須です。
keyname: 値を取得するキー。このパラメータの値は STRING データ型です。このパラメータは必須です。
手順
1. UDF を記述する
Java UDF のサンプルコード
package com.aliyun.rewrite; // パッケージ名を指定します。
import com.aliyun.odps.udf.UDF;
import java.util.HashMap;
import java.util.Map;
public class ExtractKeyValue extends UDF{
private static final int KEY_VALUE_LENGTH = 2;
/**
* split1 を使用して文字列をキーと値のペアに分割します。次に、split2 を使用してキーと値のペアをキーと値に分割します。
* @param str ソース文字列。
* @param split1 文字列をキーと値のペアに分割するために使用するデリミタ。
* @param split2 キーと値のペアをキーと値に分割するために使用するデリミタ。
* @param keyname 値を取得するキーの名前。
* @return 戻り値。
*/
public String evaluate(String str, String split1, String split2, String keyname) {
try {
// split1 を使用して文字列をキーと値のペアに分割します。
if (str == null || "".equals(str)) {
return null;
}
Map<String, String> keyValueCache = new HashMap<>(8);
String[] extractedKeyValues = str.split(split1);
// 取得したキーと値のペアを split2 を使用してキーと値に分割します。
for (String keyValue : extractedKeyValues) {
storeKeyValue(keyValueCache, keyValue, split2);
}
// 指定されたキーの値を取得します。
return keyValueCache.get(keyname);
} catch (Exception e) {
return null;
}
}
/**
* split パラメータを使用してキーと値のペアを分割します。次に、取得した結果を keyValueCache にキャッシュします。
*
* @param keyValueCache 分割後に取得されたキャッシュされたキーと値のペア。
* @param keyValue 分割するキーと値のペア。
* @param split デリミタ。
*/
private void storeKeyValue(Map<String, String> keyValueCache, String keyValue, String split) {
if (keyValue == null || "".equals(keyValue)) {
return;
}
String[] keyValueArr = keyValue.split(split);
if (keyValueArr.length == KEY_VALUE_LENGTH) {
keyValueCache.put(keyValueArr[0], keyValueArr[1]);
}
}
}Java で UDF を記述する場合は、UDF クラスを継承する必要があります。この例では、evaluate メソッドは、STRING データ型の 4 つの入力パラメータと STRING データ型の戻り値を定義しています。入力パラメータと戻り値のデータ型は、SQL 文における UDF のシグネチャとして使用されます。その他のコードの仕様と要件については、「Java UDF」をご参照ください。
Python 3 UDF のサンプルコード
from odps.udf import annotate
@annotate("string,string,string,string->string")
class ExtractKeyValue(object):
def evaluate(self, s, split1, split2, keyname):
if not s:
return None
# split1 を使用して文字列をキーと値のペアに分割し、split2 を使用してキーと値のペアをキーと値に分割します。
key_value_cache = dict(kv.split(split2) for kv in s.split(split1) if kv)
# 指定されたキーの値を取得します。
return key_value_cache.get(keyname)デフォルトでは、MaxCompute プロジェクトで UDF を実行するために Python 2 が使用されます。Python 3 で UDF を実行する場合は、セッションレベルで次のコマンドを実行します: set odps.sql.python.version=cp37。Python 3 UDF の仕様の詳細については、「Python 3 UDF」をご参照ください。
Python 2 UDF のサンプルコード
#coding:utf-8
from odps.udf import annotate
@annotate("string,string,string,string->string")
class ExtractKeyValue(object):
def evaluate(self, s, split1, split2, keyname):
if not s:
return None
# split1 を使用して文字列をキーと値のペアに分割し、split2 を使用してキーと値のペアをキーと値に分割します。
key_value_cache = dict(kv.split(split2) for kv in s.split(split1) if kv)
# 指定されたキーの値を取得します。
return key_value_cache.get(keyname)Python 2 で記述された UDF コードに漢字が含まれている場合、UDF を実行するとエラーが返されます。この問題に対処するには、コードのヘッダーにエンコーディング宣言を追加する必要があります。宣言の形式は #coding:utf-8 または # -*- coding: utf-8 -*- です。2 つの形式は同等です。Python 2 UDF の仕様の詳細については、「Python 2 UDF」をご参照ください。
2. リソースをアップロードし、UDF を作成する
UDF コードを開発およびデバッグした後、リソースを MaxCompute にアップロードし、UDF を作成します。この例では、UDF_EXTRACT_KEY_VALUE という名前の UDF を作成します。リソースをアップロードして Java UDF を作成する方法の詳細については、「Java プログラムをパッケージ化し、パッケージをアップロードして、MaxCompute UDF を作成する」をご参照ください。リソースをアップロードして Python UDF を作成する方法の詳細については、「Python プログラムをアップロードして MaxCompute UDF を作成する」をご参照ください。
3. UDF を使用する
UDF を作成した後、次のコマンドを実行して、キーと値のペアの文字列から name キーの値を取得します。
set odps.sql.python.version=cp37; -- Python 3 で UDF を使用するには、このコマンドを実行します。
SELECT UDF_EXTRACT_KEY_VALUE('name:zhangsan;age:21;',';',':','name');次の結果が返されます。
+----------+
| _c0 |
+----------+
| zhangsan |
+----------+