La méthode de tri suivante fonctionne parfaitement.

def sort_view_items(self):

    cs = self.settings.case_sensitive

    if self.settings.sort_by_file_name:
        sk = lambda vi: (vi.name if cs else vi.name.lower(), vi.group, vi.tab)

    elif self.settings.sort_by_folder:
        sk = lambda vi: (vi.folder, vi.name if cs else vi.name.lower())

    elif self.settings.sort_by_syntax:
        sk = lambda vi: (vi.syntax, vi.name if cs else vi.name.lower())

    elif self.settings.sort_by_indexes:
        sk = lambda vi: (vi.group, vi.tab)

    self.view_items.sort(key = sk)

Cependant, la section relative à la casse des lambdas vi.name if cs else vi.name.lower() est utilisée 3 fois, ce qui contrarie mon gène code répété.

Par intérêt, l'aspect cas peut-il être défini à l'avance d'une manière ou d'une autre, mais sans apporter de modifications permanentes à l'attribut name ou le faire dans une copie temporaire de la liste view_items?

Par exemple, j'ai essayé d'utiliser un lambda dans un lambda qui, selon moi, ne fonctionnerait pas et, devinez quoi, cela n'a pas fonctionné. Bien que la syntaxe ait été acceptée de manière inattendue (sans exception), elle n'a tout simplement pas entraîné le tri effectif.

def sort_view_items(self):

    cs = self.settings.case_sensitive

    name_lambda = lambda vi: vi.name if cs else vi.name.lower()

    if self.settings.sort_by_file_name:
        sk = lambda vi: (name_lambda, vi.group, vi.tab)

    ...
11
mattst 7 août 2016 à 17:07

3 réponses

Meilleure réponse

Vous devez réellement appeler name_lambda:

sk = lambda vi: (name_lambda(vi), vi.group, vi.tab)

Dans votre extrait de code, name_lambda est défini correctement mais il ne sera jamais appelé.

5
flornquake 7 août 2016 à 14:11

Cela vous oblige à ajouter une nouvelle propriété, "lower_name", à votre classe, mais cette seule modification vous permet de grandement simplifier le reste du code.

from operator import attrgetter

class Things(object):
    @property
    def lower_name(self):
        return self.name.lower()

    def sort_view_items(self):
        name_field = "name" if self.settings.case_sensitive else "lower_name"

        if self.settings.sort_by_file_name:
            fields = (name_field, "group", "tab")
        elif self.settings.sort_by_folder:
            fields = ("folder", name_field)
        elif self.settings.sort_by_syntax:
            fields = ("syntax", name_field)
        elif self.settings.sort_by_indexes:
            fields = ("group", "tab")

        self.view_items.sort(key=attrgetter(*fields))
5
chepner 7 août 2016 à 16:38

Puisque vous souhaitez l'utiliser dans 3 des 4 conditions, le meilleur moyen de refuser cette répétition, est de calculer le nom en haut de vos conditions if. Vous pouvez également utiliser un mot clé def pour créer correctement votre fonction key et renvoyer la valeur correspondante, au lieu de définir une fonction à chaque fois. Dans ce cas, vous pouvez passer le vi à key_func et calculer le name le niveau supérieur de cette fonction.

def sort_view_items(self):

    def key_func(vi):
        name = vi.name if self.settings.case_sensitive else vi.name.lower()
        if self.settings.sort_by_file_name:
            return name(vi), vi.group, vi.tab

        elif self.settings.sort_by_folder:
            return vi.folder,name(vi)

        elif self.settings.sort_by_syntax:
            return vi.syntax, name(vi)

        elif self.settings.sort_by_indexes:
            return vi.group, vi.tab

    self.view_items.sort(key=key_func)
1
Kasramvd 7 août 2016 à 21:54