XXXX redacted: Difference between revisions
Content added Content deleted
(→{{header|Lua}}: added Lua solution) |
(Added Swift solution) |
||
Line 1,015: | Line 1,015: | ||
[p│s│o] Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX. |
[p│s│o] Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX. |
||
[p│i│o] XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX. |
[p│i│o] XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing XXX "XXXXXXX" brand XXXXXXXX. XXXXXX so XXX. |
||
</pre> |
|||
=={{header|Swift}}== |
|||
{{trans|AppleScript}} |
|||
<lang swift>import Foundation |
|||
struct RedactionOptions: OptionSet { |
|||
let rawValue: Int |
|||
static let wholeWord = RedactionOptions(rawValue: 1 << 0) |
|||
static let overKill = RedactionOptions(rawValue: 1 << 1) |
|||
static let caseInsensitive = RedactionOptions(rawValue: 1 << 2) |
|||
} |
|||
func redact(text: String, target: String, options: RedactionOptions) throws -> String { |
|||
// Set up a regex search pattern for the specified target. |
|||
// Since it has to be able to match grapheme characters which may |
|||
// be combinations of others in the same string, include catches |
|||
// for "Zero Width Joiner" characters. |
|||
var pattern = "(?<!\\u200d)" + NSRegularExpression.escapedPattern(for: target) + "(?!\\u200d)" |
|||
if options.contains(.wholeWord) { |
|||
// Don't match where preceded or followed by either a hyphen |
|||
// or anything which isn't punctuation or white space. |
|||
pattern = "(?<![-[^[:punct:]\\s]])" + pattern + "(?![-[^[:punct:]\\s]])" |
|||
} else if options.contains(.overKill) { |
|||
// Include any preceding or following run of hyphens and/or |
|||
// non-(punctuation or white-space). |
|||
pattern = "[-[^[:punct:]\\s]]*" + pattern + "[-[^[:punct:]\\s]]*+" |
|||
} |
|||
// Default to case-sensitivity. |
|||
if options.contains(.caseInsensitive) { |
|||
pattern = "(?i)" + pattern |
|||
} |
|||
let regex = try NSRegularExpression(pattern: pattern) |
|||
let mutableText = NSMutableString(string: text) |
|||
// Locate all the matches in the text and replace each character |
|||
// or grapheme in the matched ranges with "X". |
|||
for match in regex.matches(in: text, range: NSRange(text.startIndex..., in: text)) { |
|||
mutableText.replaceOccurrences(of: ".(?:\\u200d.)*+", with: "X", |
|||
options: .regularExpression, range: match.range) |
|||
} |
|||
return mutableText as String |
|||
} |
|||
func optionString(options: RedactionOptions) -> String { |
|||
var result = options.contains(.wholeWord) ? "w" : "p" |
|||
result.append("|") |
|||
result.append(options.contains(.caseInsensitive) ? "i" : "s") |
|||
result.append("|") |
|||
result.append(options.contains(.overKill) ? "o" : "n") |
|||
return result |
|||
} |
|||
func doBasicTest(target: String, options: RedactionOptions) { |
|||
let text = "Tom? Toms bottom tomato is in his stomach while playing the \"Tom-tom\" brand tom-toms. That's so tom." |
|||
do { |
|||
try print("[\(optionString(options: options))]: \(redact(text: text, target: target, options: options))") |
|||
} catch { |
|||
print(error.localizedDescription) |
|||
} |
|||
} |
|||
func doBasicTests(target: String) { |
|||
print("Redact '\(target)':") |
|||
doBasicTest(target: target, options: .wholeWord) |
|||
doBasicTest(target: target, options: [.wholeWord, .caseInsensitive]) |
|||
doBasicTest(target: target, options: []) |
|||
doBasicTest(target: target, options: .caseInsensitive) |
|||
doBasicTest(target: target, options: .overKill) |
|||
doBasicTest(target: target, options: [.overKill, .caseInsensitive]) |
|||
} |
|||
func doExtraTest(target: String) { |
|||
let text = "🧑 👨 🧔 👨👩👦" |
|||
do { |
|||
try print("Redact '\(target)':\n[w]: \(redact(text: text, target: target, options: .wholeWord))") |
|||
} catch { |
|||
print(error.localizedDescription) |
|||
} |
|||
} |
|||
doBasicTests(target: "Tom") |
|||
print() |
|||
doBasicTests(target: "tom") |
|||
print() |
|||
doExtraTest(target: "👨") |
|||
print() |
|||
doExtraTest(target: "👨👩👦")</lang> |
|||
{{out}} |
|||
<pre> |
|||
Redact 'Tom': |
|||
[w|s|n]: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so tom. |
|||
[w|i|n]: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX. |
|||
[p|s|n]: XXX? XXXs bottom tomato is in his stomach while playing the "XXX-tom" brand tom-toms. That's so tom. |
|||
[p|i|n]: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX. |
|||
[p|s|o]: XXX? XXXX bottom tomato is in his stomach while playing the "XXXXXXX" brand tom-toms. That's so tom. |
|||
[p|i|o]: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX. |
|||
Redact 'tom': |
|||
[w|s|n]: Tom? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX. |
|||
[w|i|n]: XXX? Toms bottom tomato is in his stomach while playing the "Tom-tom" brand tom-toms. That's so XXX. |
|||
[p|s|n]: Tom? Toms botXXX XXXato is in his sXXXach while playing the "Tom-XXX" brand XXX-XXXs. That's so XXX. |
|||
[p|i|n]: XXX? XXXs botXXX XXXato is in his sXXXach while playing the "XXX-XXX" brand XXX-XXXs. That's so XXX. |
|||
[p|s|o]: Tom? Toms XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX. |
|||
[p|i|o]: XXX? XXXX XXXXXX XXXXXX is in his XXXXXXX while playing the "XXXXXXX" brand XXXXXXXX. That's so XXX. |
|||
Redact '👨': |
|||
[w]: 🧑 X 🧔 👨👩👦 |
|||
Redact '👨👩👦': |
|||
[w]: 🧑 👨 🧔 X |
|||
</pre> |
</pre> |
||