es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El tipo de valor de la ruta clave ‘Int’ no se puede convertir al tipo contextual ‘String’.

Estoy tratando de pasar múltiples tuplas que contienen un KeyPath y un tipo de ordenamiento a un método que debe realizar una ordenación.

Tengo este método:

extension Array {
    mutating func sort<t: comparable="">(by criteria: (path: KeyPath<element, t="">, order:OrderType)...) {

        criteria.forEach { path, order in
            //...
            sort { first, second in
            order.makeComparator()(
                first[keyPath: path],
                second[keyPath: path]
            )
        }
        }
    }
}

y lo estoy usando de la siguiente manera:

var posts = BlogPost.examples

posts.sort(by: (path:\.pageViews, order: .asc), (path:\.sessionDuration, order: .desc))

Ahora, dado que tanto las propiedades pageViews como sessionDuration son enteros, esto funcionará.

Pero si quiero pasar dos propiedades de diferentes tipos (por ejemplo, una cadena de texto y un entero), obtengo este error:

El tipo de valor de la ruta de acceso clave 'Int' no se puede convertir en el tipo contextual 'String'.

Aquí está el resto del código, pero supongo que no es tan relevante:

enum OrderType: String {
    case asc
    case desc
}

extension OrderType {
    func makeComparator<t: comparable="">() -> (T, T) -> Bool {
        switch self {
        case .asc:
            return (<)
        case .desc:
            return (>)
        }
    }
}

¿Cómo debo definir el método de ordenación para que acepte key paths heterogéneos?</element,>

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para que el método sort acepte rutas de clave heterogéneas, es necesario hacerlo genérico con dos parámetros de tipo. Uno para el tipo de la ruta de clave y otro para el tipo del orden. La nueva implementación se vería así:

    extension Array {
        mutating func sort<key, order="">(by criteria: (path: KeyPath<element, key="">, order: Order)...) where Order: RawRepresentable, Order.RawValue == String, Key: Comparable {
    
            criteria.forEach { path, order in
                sort {
                    first, second in
                    order.makeComparator()(first[keyPath: path], second[keyPath: path])
                }
            }
        }
    }
    

    Aquí, especificamos los tipos Key y Order, y también agregamos una cláusula where con dos restricciones:

    • Order debe ser RawRepresentable con un valor en bruto de String. Esto se debe a que usamos el enum OrderType para representar el orden de clasificación, y tiene un valor en bruto de String.
    • Key debe ser Comparable. Esto se debe a que necesitamos poder comparar valores de la ruta de clave al ordenar.

    Con estos cambios, ahora puedes pasar tuplas de rutas de clave heterogéneas al método sort:

    var posts = BlogPost.examples
    
    posts.sort(by: 
        (path:\.pageViews, order: OrderType.asc),
        (path:\.title, order: OrderType.desc)
    )
    

    Esto ordenará el arreglo de objetos BlogPost por pageViews en orden ascendente y luego por title en orden descendente.</element,></key,>

Comments are closed.