sha
sha

Reputation: 17860

Is there joinWithSeparator for attributed strings

Array of strings can be joined together with specific separator using joinWithSeparator method.

let st = [ "apple", "pie", "potato" ]
st.joinWithSeparator(", ")

As a result we will have "apple, pie, potato".

What if I have attributed strings inside my array? Is there easy way to combine them into one big attributed string?

Upvotes: 18

Views: 6241

Answers (4)

Roman Podymov
Roman Podymov

Reputation: 4521

Took this solution from SwifterSwift, it's similar to the other ones:

public extension Array where Element: NSAttributedString {
    func joined(separator: NSAttributedString) -> NSAttributedString {
        guard let firstElement = first else { return NSMutableAttributedString(string: "") }
        return dropFirst().reduce(into: NSMutableAttributedString(attributedString: firstElement)) { result, element in
            result.append(separator)
            result.append(element)
        }
    }

    func joined(separator: String) -> NSAttributedString {
        guard let firstElement = first else { return NSMutableAttributedString(string: "") }
        let attributedStringSeparator = NSAttributedString(string: separator)
        return dropFirst().reduce(into: NSMutableAttributedString(attributedString: firstElement)) { result, element in
            result.append(attributedStringSeparator)
            result.append(element)
        }
    }
}

Upvotes: 2

mixel
mixel

Reputation: 25846

Swift 5:

import Foundation

extension Sequence where Iterator.Element == NSAttributedString {
    func joined(with separator: NSAttributedString) -> NSAttributedString {
        return self.reduce(NSMutableAttributedString()) {
            (r, e) in
            if r.length > 0 {
                r.append(separator)
            }
            r.append(e)
            return r
        }
    }

    func joined(with separator: String = "") -> NSAttributedString {
        return self.joined(with: NSAttributedString(string: separator))
    }
}

Swift 4:

import Foundation

extension SequenceType where Generator.Element: NSAttributedString {
    func joinWithSeparator(separator: NSAttributedString) -> NSAttributedString {
        var isFirst = true
        return self.reduce(NSMutableAttributedString()) {
            (r, e) in
            if isFirst {
                isFirst = false
            } else {
                r.appendAttributedString(separator)
            }
            r.appendAttributedString(e)
            return r
        }
    }

    func joinWithSeparator(separator: String) -> NSAttributedString {
        return joinWithSeparator(NSAttributedString(string: separator))
    }
}

Upvotes: 28

Pietro Basso
Pietro Basso

Reputation: 1423

Updated answer for Swift 4, together with some basic documentation, using Sequence:

extension Sequence where Iterator.Element: NSAttributedString {
    /// Returns a new attributed string by concatenating the elements of the sequence, adding the given separator between each element.
    /// - parameters:
    ///     - separator: A string to insert between each of the elements in this sequence. The default separator is an empty string.
    func joined(separator: NSAttributedString = NSAttributedString(string: "")) -> NSAttributedString {
        var isFirst = true
        return self.reduce(NSMutableAttributedString()) {
            (r, e) in
            if isFirst {
                isFirst = false
            } else {
                r.append(separator)
            }
            r.append(e)
            return r
        }
    }

    /// Returns a new attributed string by concatenating the elements of the sequence, adding the given separator between each element.
    /// - parameters:
    ///     - separator: A string to insert between each of the elements in this sequence. The default separator is an empty string.
    func joined(separator: String = "") -> NSAttributedString {
        return joined(separator: NSAttributedString(string: separator))
    }
}

Upvotes: 8

tolbard
tolbard

Reputation: 1273

For Swift 3.0, Sequence type wasn't supported the I switch to Array. I also change the method name to use the swift 3.0 style

extension Array where Element: NSAttributedString {
    func joined(separator: NSAttributedString) -> NSAttributedString {
        var isFirst = true
        return self.reduce(NSMutableAttributedString()) {
            (r, e) in
            if isFirst {
                isFirst = false
            } else {
                r.append(separator)
            }
            r.append(e)
            return r
        }
    }

    func joined(separator: String) -> NSAttributedString {
        return joined(separator: NSAttributedString(string: separator))
    }
}

Upvotes: 7

Related Questions