You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

递归遍历嵌套字典列表的情感计算函数返回None且输出不稳定排查

问题分析与修复方案

嘿,咱们来拆解下你的walk函数为啥返回None还输出不稳定,然后一步步把它修好:

原代码的核心问题

  • 递归调用白忙活了:碰到嵌套列表时,你调用了walk(ele)但完全没管它返回的结果,深层的字典根本没被处理就丢了,等于递归白做了。
  • 情感计算粒度错了:你用str(ele.values())把整个字典的所有值拼成一串去算情感,这样得到的是整个字典内容的综合得分,没法对应到每个键值对,和你预期的“每个字段单独有得分”完全不符。
  • 变量越改越乱:new_sentiment每次循环字典都会被重新赋值,最后只留得下最后一个字典的结果;而且sentimentos在函数开头就初始化,递归的时候会被重置,深层数据的情感得分直接丢没了。
  • 返回结构不对:你预期输出是列表包字典,但原函数返回的是单个字典,要是输入是多层嵌套,最后很可能因为没处理到顶层逻辑返回空字典,甚至在某些分支下返回None。

修复后的完整代码

def walk(lst):
    result = []  # 专门用来收集所有处理好的字典
    for ele in lst:
        if isinstance(ele, list):
            # 递归处理嵌套列表,把结果合并到当前列表里
            result.extend(walk(ele))
        elif isinstance(ele, dict):
            processed_dict = {}
            for key, value in ele.items():
                # 对每个字段的值单独计算情感得分
                score_list = calcula_sentimento(str(value))
                # 取得分平均值(如果没得分就设为0,避免报错)
                avg_score = sum(score_list)/len(score_list) if score_list else 0.0
                processed_dict[key] = [value, avg_score]
            result.append(processed_dict)
    return result

# 你的calcula_sentimento函数保持不变
def calcula_sentimento(doc):
    sentences = nltk.sent_tokenize(doc)
    stokens = [nltk.word_tokenize(sent) for sent in sentences]
    taggedlist=[]
    for stoken in stokens:
        taggedlist.append(nltk.pos_tag(stoken))
    wnl = nltk.WordNetLemmatizer()
    score_list=[]
    for idx,taggedsent in enumerate(taggedlist):
        score_list.append([])
        for idx2,t in enumerate(taggedsent):
            newtag=''
            lemmatized=wnl.lemmatize(t[0])
            if t[1].startswith('NN'):
                newtag='n'
            elif t[1].startswith('JJ'):
                newtag='a'
            elif t[1].startswith('V'):
                newtag='v'
            elif t[1].startswith('R'):
                newtag='r'
            else:
                newtag=''
            if(newtag!=''):
                synsets = list(swn.senti_synsets(lemmatized, newtag))
                score=0
                if(len(synsets)>0):
                    for syn in synsets:
                        score+=syn.pos_score()-syn.neg_score()
                    score_list[idx].append(score/len(synsets))
    sentence_sentiment=[]
    for score_sent in score_list:
        try:
            sentence_sentiment.append(sum([word_score for word_score in score_sent])/len(score_sent))
        except ZeroDivisionError as err:
            pass
    return sentence_sentiment

关键修复点说明

  1. 递归结果不丢了:遇到嵌套列表时,用result.extend(walk(ele))把递归返回的处理好的字典列表合并到当前结果里,深层的嵌套结构再也不会被忽略。
  2. 每个字段单独算分:对字典里的每个值单独调用calcula_sentimento,计算这个值的情感得分,然后取平均值(因为你的calcula_sentimento返回的是句子级别的得分列表,单个值可能对应一个句子,取平均更合理)。
  3. 结果收集更靠谱:用result列表统一收集所有处理后的字典,最后返回这个列表,完全符合你预期的输出结构。
  4. 变量不再乱覆盖:每个字典处理时单独创建processed_dict,不会被后续的字典覆盖,确保每个字典都被正确处理并加入结果。

测试一下

用你给的输入样例跑一遍:

input_data = [[{'A0': 'Up to 140 asylum seekers', 'V': 'overpowered', 'A1': 'security guards', 'AM-LOC': 'at the tunnel s entrance', 'AM-TMP': 'as trains passed by dangerously close'}, {'A0': 'Up to 140 asylum seekers', 'V': 'swarmed on', 'A1': 'to the tracks', 'AM-TMP': 'as trains passed by dangerously close'}, {'A1': 'trains', 'V': 'passed', 'A2': 'by dangerously close'}]]

output = walk(input_data)
print(output)

会得到和你预期一致的结构,比如:

[
    {'A0': ['Up to 140 asylum seekers', 0.0], 'V': ['overpowered', -0.125], 'A1': ['security guards', 0.0], 'AM-LOC': ['at the tunnel s entrance', 0.0], 'AM-TMP': ['as trains passed by dangerously close', -0.0625]},
    {'A0': ['Up to 140 asylum seekers', 0.0], 'V': ['swarmed on', 0.0], 'A1': ['to the tracks', 0.0], 'AM-TMP': ['as trains passed by dangerously close', -0.0625]},
    {'A1': ['trains', 0.0], 'V': ['passed', 0.0], 'A2': ['by dangerously close', -0.125]}
]

(具体得分取决于SentiWordNet的计算结果)

内容的提问来源于stack exchange,提问作者hjmnzs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:41:30