Since both attributes are on the same feature (from your screenshot), I would use a Tester transformer to test:
Hope this helps.
Thanks Erik. I was hoping there was a way to iterate over all of the values from one attribute and check each of them against the values in the other attribute. Ideally I would be able to use a tester, but with a much simpler set up. Something like:
(This returns from what I can tell just random/bad data.)
While there is a maximum amount of possibilities that I could test for (only 3x possible phases on the XFMR, another 3x on the primary), i'd like to be able to find a way to do this without having to test out each possibility in the tester individually.
Thanks Erik. I was hoping there was a way to iterate over all of the values from one attribute and check each of them against the values in the other attribute. Ideally I would be able to use a tester, but with a much simpler set up. Something like:
(This returns from what I can tell just random/bad data.)
While there is a maximum amount of possibilities that I could test for (only 3x possible phases on the XFMR, another 3x on the primary), i'd like to be able to find a way to do this without having to test out each possibility in the tester individually.
The issue with this approach is that A,C is not in A,B,C, all other matches could be caught by PrimaryPhase CONTAINS XFMRPhase.
That would definitely shorten the number of options to 2:
PrimaryPhase CONTAINS XFMRPhase OR
PrimaryPhase = A,B,C AND XFMRPhase = A,C.
I have a very horrible approach that I used when trying to do something similar for advent of code and avoiding python, I'd never do it in day to day work! It basically reformulates the values as a regular expression then searches for that regular expression
Left Value
@FindRegEx(@Value(PrimaryPhase),@ReplaceString(@ReplaceRegEx(@Value(XFMRPhase),(eA-Z]),(?=.*\1)),",",""))
So for example
If PrimaryPhase is A,B,C and XFMRPhase is B,C the XFMRPhase is converted to a regular expression
(?=.*B)(?=.*C)
It then looks for this regular expression in the PrimaryPhase attribute, if there is a match it returns 0 and passes the test, otherwise it returns -1 and fails the test
Edit: It's actually slightly simpler if you put use the same test in an AttributeValidator
OK, one method is this:
- Add an AttributeSplitter
- Split the XFMRPhase attribute
- Split on the , character
- Put into a list (say called xList)
- Add a Tester
- Test for:
- @FindRegEx(@Value(PrimaryPhase),(?=.*@Value(xList{0}))(?=.*@Value(xList{1}))(?=.*@Value(xList{2})))
- !=
- -1
That seems to work for me. It assumes you don't have more than 3 items in the XFMR list.
Demo workspace: phasechecker.fmw
OK, one method is this:
- Add an AttributeSplitter
- Split the XFMRPhase attribute
- Split on the , character
- Put into a list (say called xList)
- Add a Tester
- Test for:
- @FindRegEx(@Value(PrimaryPhase),(?=.*@Value(xList{0}))(?=.*@Value(xList{1}))(?=.*@Value(xList{2})))
- !=
- -1
That seems to work for me. It assumes you don't have more than 3 items in the XFMR list.
Demo workspace: phasechecker.fmw
The Regex part says the PrimaryPhase has to contain the first XFMRPhase AND the second XFMRPhase AND the third XFMRPhase. If it does then it returns zero, else it returns -1. At least, it works in all the testing I've done. It doesn't seem to matter if there are not 3 values. ie if xList{2} doesn't exist, it doesn't seem to cause a mismatch.
OK, one method is this:
- Add an AttributeSplitter
- Split the XFMRPhase attribute
- Split on the , character
- Put into a list (say called xList)
- Add a Tester
- Test for:
- @FindRegEx(@Value(PrimaryPhase),(?=.*@Value(xList{0}))(?=.*@Value(xList{1}))(?=.*@Value(xList{2})))
- !=
- -1
That seems to work for me. It assumes you don't have more than 3 items in the XFMR list.
Demo workspace: phasechecker.fmw
Since the AttributeSplitter is mostly regex and regsub, I think it likely you could encapsulate that part into the Tester string too; I haven't tried it, but I'm about 75% certain it could be done.
I have a very horrible approach that I used when trying to do something similar for advent of code and avoiding python, I'd never do it in day to day work! It basically reformulates the values as a regular expression then searches for that regular expression
Left Value
@FindRegEx(@Value(PrimaryPhase),@ReplaceString(@ReplaceRegEx(@Value(XFMRPhase),(eA-Z]),(?=.*\1)),",",""))
So for example
If PrimaryPhase is A,B,C and XFMRPhase is B,C the XFMRPhase is converted to a regular expression
(?=.*B)(?=.*C)
It then looks for this regular expression in the PrimaryPhase attribute, if there is a match it returns 0 and passes the test, otherwise it returns -1 and fails the test
Edit: It's actually slightly simpler if you put use the same test in an AttributeValidator
Creating regexes on the fly must be the ultimate high level FME hack!
Creating regexes on the fly must be the ultimate high level FME hack!
In real life, I'd go to python for this, as it gives some more control on reporting what doesn't match.
import fme
import fmeobjects
def processFeature(feature):
primary = feature.getAttribute('PrimaryPhase').split(',')
xfmr = feature.getAttribute('XFMRPhase').split(',')
templist = ri for i in xfmr if i not in primary]
if len(templist) == 0:
feature.setAttribute("outcome",'pass')
else:
feature.setAttribute("outcome",'fail')
feature.setAttribute("missing_phases", ','.join(templist))
But I'd given myself some no python rules for advent of code - sometimes fme is harder than python!
I think this is the easiest way, using the Tester:
The only clause not covered by the contains is when the XFMRPhase = A,C and the PrimaryPhase has all phases.
Hope this helps.
OK, one method is this:
- Add an AttributeSplitter
- Split the XFMRPhase attribute
- Split on the , character
- Put into a list (say called xList)
- Add a Tester
- Test for:
- @FindRegEx(@Value(PrimaryPhase),(?=.*@Value(xList{0}))(?=.*@Value(xList{1}))(?=.*@Value(xList{2})))
- !=
- -1
That seems to work for me. It assumes you don't have more than 3 items in the XFMR list.
Demo workspace: phasechecker.fmw
I feel like i'm missing something somewhere. (Opening up the demo bench doesn't work, we're running 2018.1.2.0 currently)
Here's how I set up the tester:
Regex:
@FindRegEx(@Value(PRIMARYPHASE),(?=.*@Value(_PhaseList{0}))(?=.*@Value(_PhaseList{1}))(?=.*@Value(_PhaseList{2})))
The results i'm seeing in output to Passed seem to be correct, but then i'm just getting weird results that should be passing out of the Failed output:
I feel like i'm missing something somewhere. (Opening up the demo bench doesn't work, we're running 2018.1.2.0 currently)
Here's how I set up the tester:
Regex:
@FindRegEx(@Value(PRIMARYPHASE),(?=.*@Value(_PhaseList{0}))(?=.*@Value(_PhaseList{1}))(?=.*@Value(_PhaseList{2})))
The results i'm seeing in output to Passed seem to be correct, but then i'm just getting weird results that should be passing out of the Failed output:
The tester should be set up like this
The tester should be set up like this
That seemed to the do the trick. This looks like it's working, but now i'm noticing incorrect results because of the way i'm joining the phasing over from the XFMR to the Primary.
C'est la FME as they say.
I still am not extremely clear on using RegEx, so I appreciate the examples in here even though i'll admit that I don't quite understand them just yet.