69810
# 前提・実現したいこと

前の質問「[文中の単語を大文字から小文字に変換する時に、固有名詞や文頭の語だけ除外する方法について](https://ja.stackoverflow.com/questions/69188/%E6%96%87%E4%B8%AD%E3%81%AE%E5%8D%98%E8%AA%9E%E3%82%92%E5%A4%A7%E6%96%87%E5%AD%97%E3%81%8B%E3%82%89%E5%B0%8F%E6%96%87%E5%AD%97%E3%81%AB%E5%A4%89%E6%8F%9B%E3%81%99%E3%82%8B%E6%99%82%E3%81%AB-%E5%9B%BA%E6%9C%89%E5%90%8D%E8%A9%9E%E3%82%84%E6%96%87%E9%A0%AD%E3%81%AE%E8%AA%9E%E3%81%A0%E3%81%91%E9%99%A4%E5%A4%96%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/69193?noredirect=1#comment76775_69193)」に関連する質問で、問題はPythonのjoin関数の使い方です。

プログラムで入力と出力が以下のようになっているのですが、それをピリオドやカンマ、アポストロフィーでは空白をなくした形にしたいです。

```

    #入力
    Kate forgot John's login ID, and was not able to use the computer.
    
    #出力
    Kate forgot John 's login id , and was not able to use the computer .
    
    #求めたい出力
    Kate forgot John's login id, and was not able to use the computer.
    
    
```

# 問題と試したこと

現在の出力は以下のようになっており、

```

    Kate forgot John 's login id , and was not able to use the computer .
    
```

join関数の"
"（空白）をなくすと`print("".join(conved))`、以下の出力になり、どうすれば求めたい出力を得られるjoin関数の使い方をできるのかわからない状態です。

```

    KateforgotJohn'sloginid,andwasnotabletousethecomputer.
    
```

# 実行中のコード

```

    import nltk
    
    sentences = """Kate forgot John's login ID, and was not able to use the computer.
    """
    
    def replace_if_all_uppercase(word):
        # もし単語のすべての文字が大文字ならば、すべて小文字に変換
        if all(map(lambda w: w.isupper(), word[0].split())):
            return word[0].lower()
        
        return word[0]
        
    
    for sentence in sentences.splitlines():
        # nltkを使って分かち書き＆品詞の取得
        tokens = nltk.word_tokenize(sentence)
        tagged = nltk.pos_tag(tokens)
        conved = list(map(lambda s: replace_if_all_uppercase(s), tagged))
        print(" ".join(conved))
    
```
CC BY-SA 4.0
2020-08-23T14:26:46.173
69808
2020-08-23T15:15:17.693
32568
question
python python3 自然言語処理
Pythonでjoin関数を使用するときにピリオドやカンマでは間を開けないようにしたい
以下は
[functools.reduce()](https://docs.python.org/3/library/functools.html#functools.reduce)
を使う方法です。

```

    from functools import reduce
    
             :
    
    for sentence in sentences.splitlines():
        # nltkを使って分かち書き＆品詞の取得
        tokens = nltk.word_tokenize(sentence)
        tagged = nltk.pos_tag(tokens)
        conved = list(map(lambda s: replace_if_all_uppercase(s), tagged))
        print(reduce(
          lambda x, y: x+y if y.startswith(('.', ',', "'")) else x+' '+y, conved))
    
    =>
    Kate forgot John's login id, and was not able to use the computer.
    
```
CC BY-SA 4.0
2020-08-23T14:51:10.200
69809
2020-08-23T14:51:10.200
69808
answer
[Python Untokenize a sentence - Stack
Overflow](https://stackoverflow.com/questions/21948019/python-untokenize-a-
sentence) が参考になりそうです。

私はこのnltkに詳しくないですし（というか今初めて使いました）、質問者さんも join
をお使いになりたいようなので、[joinを使っている回答](https://stackoverflow.com/a/22016830/1979953)を参考にします。

```

    import nltk
    import string
    
    sentences = """Kate forgot John's login ID, and was not able to use the computer.
    """
    
    def replace_if_all_uppercase(word):
        # もし単語のすべての文字が大文字ならば、すべて小文字に変換
        if all(map(lambda w: w.isupper(), word[0].split())):
            return word[0].lower()
        
        return word[0]
        
    
    for sentence in sentences.splitlines():
        # nltkを使って分かち書き＆品詞の取得
        tokens = nltk.word_tokenize(sentence)
        tagged = nltk.pos_tag(tokens)
        conved = list(map(lambda s: replace_if_all_uppercase(s), tagged))
    
        print("".join([" "+i if not i.startswith("'") and i not in string.punctuation else i for i in conved]).strip())
    
```

[joinを使っている回答](https://stackoverflow.com/a/22016830/1979953)のコメント部分が少し気になりますが、質問者さんが欲している文字列は今回取得できました。

実行結果:

```

    Kate forgot John's login id, and was not able to use the computer.
    
```

おそらく質問者さんであれば、本家の他の回答が参考にできるかもしれません。
CC BY-SA 4.0
2020-08-23T14:51:16.740
69810
2020-08-23T15:15:17.693
2020-08-23T15:15:17.693
9008
9008
69808
answer