寻找Python般的优雅:用字典代替重复的意大利面b

2024-04-19 18:44:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个脚本,可以将嵌套列表转换为LaTeX格式的表。棘手的部分是与细胞颜色的价值观。假设我有这样一个嵌套列表:

[[0.40,-0.13,0.00,0.00,0.00],[1.90,-0.56,-0.57,-0.66,-1.37],[4.07,0.24,2.56,0.02,0.02],[6.43,0.23,0.33,0.18,0.02],[11.80,4.81,4.86,3.96,6.03],[4.05,1.94,0.09,0.01,0.03]]

我的剧本是这样的

for fila in listainicial:
#seudocódigo
    mes1 = ""
    mes2 = ""
    mes3 = ""
    mes4 = ""
    mes5 = ""
if float(fila[0]) >= 100:
        mes1 = "\\footnotesize{}\\cellcolor{100pc}"
    elif float(fila[0]) > 30:
        mes1 = "\\footnotesize{}\\cellcolor{masde30pc}"
    elif float(fila[0]) > 20:
        mes1 = "\\footnotesize{}\\cellcolor{20to30pc}"
    elif float(fila[0]) > 10:
        mes1 = "\\footnotesize{}\\cellcolor{10to20pc}"
    elif float(fila[0]) > 5:
        mes1 = "\\footnotesize{}\\cellcolor{5to10pc}"
    elif float(fila[0]) > 0:
        mes1 = "\\footnotesize{}\\cellcolor{0to5pc}"
    elif float(fila[0]) == 0:
        mes1 = "\\footnotesize{}\\cellcolor{0pc}"
    elif float(fila[0]) > -5:
        mes1 = "\\footnotesize{}\\cellcolor{m5to0pc}"
    elif float(fila[0]) > -10:
        mes1 = "\\footnotesize{}\\cellcolor{m10tom5pc}"
    elif float(fila[0]) > -25:
        mes1 = "\\footnotesize{}\\cellcolor{m25tom10pc}"
    elif float(fila[0]) <= -25:
        mes1 = "\\footnotesize{}\\cellcolor{menosdem25pc}\\color{white}"

代码在fila[1]到fila[4]之间重复

这太不和谐了,我觉得有点脏。我的脚本可以工作,复制粘贴块不是问题,但正如我在标题中指出的那样,我希望生成一个更优雅、更令人满意的代码。你知道吗

我真的很想用一本字典来代替如此冗长单调的if…elif系列。我也将感谢任何其他解决方案,减少我的110行长的脚本部分。你知道吗

我真的很感激任何提示或解决在这个意义上

提前谢谢


Tags: 代码脚本列表if颜色格式floatlatex
3条回答

谢谢你们的回答,对我的其他问题很有启发和启发。但是,我想使用字典和遍历变量名,所以我最终以@Poshi answer开始,以这个结束

for fila in listainicial:
    ISI = ""
    mes1 = ""
    mes2 = ""
    mes3 = ""
    mes4 = ""
    mes5 = ""
    dictiocell = {"%s >= 100":"100pc", "100 > %s > 30":"masde30pc", "30 >= %s > 20":"20to30pc", "20 >= %s > 10":"10to20pc", "10 >= %s > 5":"5to10pc", "5 >= %s > 0":"0to5pc", "%s == 0":"0pc", "0 > %s > -5":"m5to0pc", "-5 >= %s > -10":"m10tom5pc", "-10 >= %s > -25":"m25tom10pc"}
    for n in range (1,6):
        for p in dictiocell:
            if eval(p %float(fila[n+2])):
                globals()["mes%s" % n] = "\\footnotesize{}\\cellcolor{" + dictiocell[p] + "}" 
        if float(fila[n+2]) <= -25:
            globals()["mes%s" % n] = "\\footnotesize{}\\cellcolor{menosdem25pc}\\color{white}"

因为它的工作,我张贴它,因为它可以帮助其他人在这里。你知道吗

再次感谢。@reblochon,您的示例启发了我在python中需要学习和改进的所有内容

您可以定义(limit,color)元组的排序列表:

colors = [(-25,'menosdem25pc'), (-10, 'm25tom10pc'), (-5, 'm10tom5pc')...]

然后,您可以筛选搜索感兴趣的内容:

list_of_bigger_tuples = [x for x in colors where x[0]>fila[0]]
first_tuple = list_of_bigger_tuples[0]
color = first_tuple[1]

现在您可以编写字符串:

result = "\\footnotesize{}\\cellcolor{" + color + "}"

这并不是您要做的:对于值<;=25,我缺少字符串的一部分,并且我假设所有的比较器都是>。但你明白了。你知道吗

下面是我试图封装您的代码并使其不那么笨拙的尝试:

if name == main以上的所有内容都可以在单独的模块中提取,使主代码如下所示:

boundaries = [float('-inf'), -25, -10, -5, 0 - EPSILON, 0 + EPSILON, 5, 10, 20, 30, 100, float('inf')]
listainicial = [the values you have]
latex_string_values =  get_latex_values(listainicial, boundaries)

我添加了docstring来解释每个类/方法的作用;如果需要更多解释,请告诉我。你知道吗

from typing import NamedTuple, List


EPSILON = 1e-8


class Interval(NamedTuple):
    """represents an interval on the number line, where the high value is included
    """
    low : float
    high : float

    def contains(self, value: float)-> bool:
        return self.low < value <= self.high


class Intervals:
    """represents a collection of Interval on the number line
    """
    def __init__(self, boundaries: List[float]):
        self.intervals = [Interval(low=low, high=high)
                          for low, high in zip(boundaries[:-1], boundaries[1:])]

    def get_interval(self, value: float)-> Interval:
        """returns the interval the value belongs to
        """
        for interval in self.intervals:
            if interval.contains(value):
                return interval
        raise ValueError('this value does not belong here')

    def __iter__(self):
        for interval in self.intervals:
            yield interval


class LatexValues:
    """a class that parses and assigns latex strings based on whether a value
    is contained in an interval
    """
    latex_values = ["\\footnotesize{}\\cellcolor{menosdem25pc}\\color{white}",
                    "\\footnotesize{}\\cellcolor{m25tom10pc}",
                    "\\footnotesize{}\\cellcolor{m10tom5pc}",
                    "\\footnotesize{}\\cellcolor{m5to0pc}",
                    "\\footnotesize{}\\cellcolor{0pc}",
                    "\\footnotesize{}\\cellcolor{0to5pc}",
                    "\\footnotesize{}\\cellcolor{5to10pc}",
                    "\\footnotesize{}\\cellcolor{10to20pc}",
                    "\\footnotesize{}\\cellcolor{20to30pc}",
                    "\\footnotesize{}\\cellcolor{masde30pc}",
                    "\\footnotesize{}\\cellcolor{100pc}"
                    ]

    def __init__(self, boundaries: List[List[float]]):

        self.boundaries = boundaries[:]
        self.intervals = Intervals(boundaries)
        self.assigned_values = {interval: latex_value for interval, latex_value
                                in zip(self.intervals, LatexValues.latex_values)}

    def get_latex(self, value: float)-> str:
        return self.assigned_values[self.intervals.get_interval(value)]


def get_latex_values(listainicial: List[List[float]], boundaries: List[float])-> List[List[str]]:
    """
    :param listainicial: a data structure that contains the values used to assign Latex strings
    :param boundaries: the boundaries of the intervals segregating the values
    :return: the appropriate latex string corresponding to a value
             a list of lists that contain the latex_values for mes1-mes5 for each fila in filainicial
    """

    latex_values = LatexValues(boundaries)
    results = []
    for fila in listainicial:
        result = []
        for mes in range(5):
            result.append(latex_values.get_latex(fila[mes]))
        results.append(result)
    return results


if __name__ == '__main__':

    boundaries = [float('-inf'), -25, -10, -5, 0 - EPSILON, 0 + EPSILON, 5, 10, 20, 30, 100, float('inf')]
    test_listainicial = [[0, 22, 43, -200, 1], [12, -4, -12, 110, 41]]
    for result in get_latex_values(test_listainicial, boundaries):
        print(result)

输出:

['\\footnotesize{}\\cellcolor{0pc}', '\\footnotesize{}\\cellcolor{20to30pc}', '\\footnotesize{}\\cellcolor{masde30pc}', '\\footnotesize{}\\cellcolor{menosdem25pc}\\color{white}', '\\footnotesize{}\\cellcolor{0to5pc}']
['\\footnotesize{}\\cellcolor{10to20pc}', '\\footnotesize{}\\cellcolor{m5to0pc}', '\\footnotesize{}\\cellcolor{m25tom10pc}', '\\footnotesize{}\\cellcolor{100pc}', '\\footnotesize{}\\cellcolor{masde30pc}']

相关问题 更多 >