属性の連結について

49 views
Skip to first unread message

TJ

unread,
Jun 29, 2017, 4:01:22 AM6/29/17
to FMEユーザーフォーラム
FME 2017.0.1.1

属性 attr1,attr2,attr3 を "-" で連結したいです。

attr2 と attr3 は空欄の場合があります。その場合、連結の際無視するようにします。

例:attr1:"A" attr2:"" attr3:"C" の場合、連結後の結果を "A-C" にしたいです。

条件式で判定して文字列連結をすればですますが、もっとシンプルのやり方がないかと考えて質問をしました。

因みに AttributeListExploder で1回属性名、属性値をリストにしたあと、ListConcatenator (Drop Empty and Null Elements を Yes)でやってみました。結果一見良さそうですが、属性順をattr2,attr1,attr3 の順にしても同じ結果になります。AttributeListExploder ではリスト作成の際、属性の順でリスト作成していないようです。今回属性の順番で連結することが重要ですので、この方法ではだめです。

他にいい方法があれば教えていただきたいです。



Takashi Iijima

unread,
Jun 29, 2017, 9:01:14 AM6/29/17
to FMEユーザーフォーラム
二通り思いつきました。

A案
  1. StringConcatenator など: attr1, attr2, attr3 の値を適当な区切り文字(例えばカンマ)をはさんで連結する。
  2. AttributeSplitter (Drop Empty Parts: Yes): 区切り文字で分割してリストに変換する。空の要素は削除する。
  3. ListConcatenator: リストの要素をハイフン (-) 区切りで連結する。
B案
  1. StringConcatenator など: attr1, attr2, attr3 の値をハイフン (-) 区切りで連結する。
  2. StringReplacer: - または文字列末尾の直前の - を削除する。
B案 StringReplacer のパラメーター:
  • Mode: Replace Regular Expression
  • Text To Replace: -(?=(-|$))
  • Replacement Text: <not set>
上の正規表現は、- または文字列末尾 ($) 直前の - と一致するので、Replacement Text に何も設定しなければ、一致したハイフンが削除されることになります。
次の文字列式は、B案と同等です。

@ReplaceRegEx(@Value(attr1)-@Value(attr2)-@Value(attr3),-(?=(-|$)),"")





TJ

unread,
Jun 29, 2017, 11:58:27 PM6/29/17
to fm...@googlegroups.com
二案のご提示ありがとうございます。

A案はシンプルで分かりやすいですね。
B案の正規表現を使う方法もとても参考になりました。
ただし、B案は、3つの属性の連結には対応できますが、4つ以上の属性で間に空欄の属性連続している("A,"","","D")の場合、"A--D" のような形になってしまいます。連続ハイフンも取る必要があると思います。

私も一つの案を考えました。
attr1,attr2,attr3 を attr.{1},attr.{2},attr.{3} に変えてから、ListConcatenator でattr.{}を連結する案です。
連結対象の属性名は規則性がなければ、AttributeManager などで名前を変更すれば対応可能です。

BulkAttributeRenamerのパラメータ設定:
    Action: Regular Expression Replace
    Mode: Rename
    Text To Find: (\d)
    String: .{\1}

ListConcatenatorのパラメータ設定:
    List Attribute: attr.{}
    Separator Character: -
    Destination Attribute: _concatenated
    Drop Empty and Null Elements: Yes

Takashi Iijima

unread,
Jun 30, 2017, 1:11:44 AM6/30/17
to fm...@googlegroups.com
> 4つ以上の属性で間に空欄の属性連続している("A,"","","D")の場合、"A--D" のような形になってしまいます。

その正規表現は、連結する属性が4つ以上の場合にも対応しているはずなんですが...
念のため次の式でテストしたところ、"A-D"が得られました。

attr1 = "A"
attr2 = ""
attr3 = ""
attr4 = "D"

@ReplaceRegEx(@Value(attr1)-@Value(attr2)-@Value(attr3)-@Value(attr4),-(?=(-|$)),"")

もう一度確認していただけませんか?

> attr1,attr2,attr3 を attr.{1},attr.{2},attr.{3} に変えてから

FMEのリストは便利な仕組みですよね。
連結する順番 = 属性名の辞書順という前提ならば、Hub の AttributeListPopulator (Populating Order: Name Ascending (Alphabetic)) も使えます。

おまけの Python バージョン。

def processFeature(feature):
    attrs = ['attr1', 'attr2', 'attr3']
    values = ['%s' % feature.getAttribute(a) for a in attrs]
    feature.setAttribute('_result', '-'.join([v for v in values if v]))

[追記] 上のスクリプトだと、属性が欠落していたときに 'None' が連結されてしまうので、次の方が良いかな。

def processFeature(feature):
    attrs = ['attr1', 'attr2', 'attr3']
    values = [feature.getAttribute(a) for a in attrs]
    feature.setAttribute('_result', '-'.join(['%s' % v for v in values if v]))

TJ

unread,
Jun 30, 2017, 5:36:38 AM6/30/17
to FMEユーザーフォーラム
失礼いたしました。私の確認不足です。
B案は確かに連続ハイフンも取り除くようになっています。

また、AttributeListPopulator と Python バージョンも教えていただいてありがとうございます。

連結する順番 = 属性名の辞書順の場合、AttributeListPopulator は属性本来の順番関係なく連結してくれるので、それはそれで便利ですね。

Takashi Iijima

unread,
Jun 30, 2017, 6:06:33 AM6/30/17
to fm...@googlegroups.com
確認できてなによりです。

A案が最も分かり易く、FME的な解決法であると思います。
個人的にはB案の正規表現が好みですが、初心者にはちょっと理解し難いかも知れません。

XML トランスフォーマーを使った方法も思いつきましたが、これは XQuery の勉強用です。JSON でも似たようなことができるかも知れません。

1. XMLTemplater
Template Expression:
----------
<attrs>{
for $attr in ("attr1", "attr2", "attr3")
let $v := fme:get-attribute($attr)
where $v != ""
return <attr>{$v}</attr>
}</attrs>
----------

2. XMLFlattener
  • Elements to Match: attrs
  • Attributes to Expose: attr{}
3. ListConcatenator

[追記] XMLFlattner に "Skip to Empty Elements" オプションがあるのを忘れていました
それを On にするか、または、ListConcatenator の "Drop Empty and Null Elements" を Yes にすれば、Template Expression は簡単になりますね。
----------
<attrs>{
for $attr in ("attr1", "attr2", "attr3")
return <attr>{fme:get-attribute($attr)}</attr>
}</attrs>
----------

Takashi Iijima

unread,
Jul 2, 2017, 10:10:42 AM7/2/17
to FMEユーザーフォーラム
この文字列式を思いつきました。これが最も簡潔かも知れません。

@Trim(@ReplaceRegEx(@Value(attr1)-@Value(attr2)-@Value(attr3),-+,-),-)

attr1, attr2, ... の値をハイフンで連結し、
@ReplaceRegEx: 連続するハイフンを1個のハイフンに置き換え、
@Trim: 前後にハイフンがあればそれらを削除する。
Reply all
Reply to author
Forward
0 new messages