在Python的字符串中获取特殊字符后的第一个单词

时间:2019-02-04 22:14:56

标签: python python-3.x dataframe

我有一些这样的字符串:

df = pd.DataFrame( [
                     [ij for ij in i]
                    for i in rows]
                  )

df.rename(columns={0: 'time', 1: 'Room1Temp', inplace=True)
df = df.sort_values(['time'], ascending=[0])

## 3 days
time = df['time'].truncate(after=144)
Room1Temp = df['Room1Temp'].truncate(after=144)


fig, ax = plt.subplots()

plt.figure(figsize=(16,6))    
plt.plot(time, Room1Temp)
plt.axhline(y=28, color='red')
plt.xlabel('Date (UTC)', fontsize=18)
plt.xticks(rotation=45)
plt.ylabel('Room 1 Temp (Celsius)', fontsize=18)
plt.gcf().subplots_adjust(bottom=0.3, left=0.05)
plt.minorticks_on()
plt.grid(b=True, which='major', linestyle='-')
plt.grid(b=True, which='minor', axis='x', linestyle=':')
plt.savefig('Room1TempPlot.png', format='png')

我想在数据框中删除@之后的单词,并从其数据框中删除该单词。 现在我用这个来取出@之后的第一个单词,但是结果在所有字符串中都不正确。

s='@VirginAmerica it was amazing, and arrived an hour early.'
t='heyyyyy@VirginAmerica , am I dreaming?'
m='heyyyyy @VirginAmerica , am I dreaming?'
u=''
f='@United...'
h='@United@VirginAmerica'

要删除@之后的单词,并写出不带@和单词的整个字符串,我会收到这些信息:

s.split(' ', 1)[0]==>correct==>VirginAmerica
t.split(' ', 1)[0]==>wrong==>heyyyyy@VirginAmerica==>'VirginAmerica' is correct 
m.split(' ', 1)[0]==>correct==>VirginAmerica
u.split(' ', 1)[0]==>correct==>''
f.split(' ', 1)[0]==>wrong==>@United...==>'United' is correct
h.split(' ', 1)[0]==>wrong==>@United@VirginAmerica==>I just want the first one

您能帮我解决这个问题吗?最好不要使用任何库。但是如果这是唯一的选择,那就可以了。

谢谢

3 个答案:

答案 0 :(得分:2)

另一个使用正则表达式的实现,它从字符串中获取@之后的单词。

import re

s='@VirginAmerica it was amazing, and arrived an hour early.'
t='heyyyyy@VirginAmerica , am I dreaming?'
m='heyyyyy @VirginAmerica , am I dreaming?'
u=''
f='@United...'
h='@United@VirginAmerica'

for text in [s, t, m, u, f, h]:
    print(re.findall(r'@(\w+)', text))

此打印

['VirginAmerica ']
['VirginAmerica ']
['VirginAmerica ']
[]
['United']
['United', 'VirginAmerica']

还请注意,re是标准的python库,因此您不会使用python尚未包含的任何内容。

如果您不想使用正则表达式,则可以仍然使用split,但是类似这样的结果将与上面相同:

s='@VirginAmerica it was amazing, and arrived an hour early.'
t='heyyyyy@VirginAmerica , am I dreaming?'
m='heyyyyy @VirginAmerica , am I dreaming?'
u=''
f='@United...'
h='@United@VirginAmerica'

for text in [s, t, m, u, f, h]:
    _, *words = text.split('@')
    print([words.split()[0] for word in words])

修改

根据您的评论,要获得@之后的单词的第一个出现,例如'united'中的第一个单词h,只需使用列表切片(请务必确保确保至少有一个与正则表达式匹配的单词,否则请尝试使用try除外(块除外)

h='@United@VirginAmerica'
re.sub(r'@(\w+)' h)[0]
#United

要获取没有首次出现@word的单词,请使用sub,在其后还添加了一个空格和问号以删除空格,以便在打印时看起来正确。 ((如果您希望它打印所有已删除的事件,只需从此方法中删除count

s='@VirginAmerica it was amazing, and arrived an hour early.'
re.sub(r'@(\w+) ?', '', s, count=1)
#it was amazing, and arrived an hour early.

我已经完成了give it a try

答案 1 :(得分:1)

这是您带有测试的代码

import re

s='@VirginAmerica it was amazing, and arrived an hour early.'
t='heyyyyy@VirginAmerica , am I dreaming?'
m='heyyyyy @VirginAmerica , am I dreaming?'
u=''
f='@United...'
h='@United@VirginAmerica'

def find_match(str):
  res = re.search('@(\w+)', str)
  if not res:
    return ''
  return res.group(1)

def sub_match(str):
  return re.sub('^[^@]*@\w+', '', str)

assert find_match(s) == 'VirginAmerica'
assert find_match(t) == 'VirginAmerica'
assert find_match(m) == 'VirginAmerica'
assert find_match(u) == ''
assert find_match(f) == 'United'
assert find_match(h) == 'United'

assert sub_match(s) == ' it was amazing, and arrived an hour early.'
assert sub_match(t) == ' , am I dreaming?'
assert sub_match(m) == ' , am I dreaming?'
assert sub_match(u) == ''
assert sub_match(f) == '...'
assert sub_match(h) == '@VirginAmerica'

find_match(str)

核心思想是使用正则表达式。

我们正在寻找第一个以@符号开头的单词。使用下一个regexp可以很容易地描述

=> @\w+

其中@表示匹配确切字符,而\w+匹配1个或更多单词字符(docs explanation for this)

我们也使用()来选择结果组,因为我们对没有@的单词感兴趣,所以只包装\w+

=> @(\w+)

sub_match(str)

它对regexp使用相同的思想,但是由于@字符的第一个匹配的情况,所以有点麻烦。

为此,我们首先匹配不是@-> [^@]*正则表达式部分的所有字符,然后使用与find_match(str)中使用的相同正则表达式,但不使用分组我们只需要将整个内容替换为@

PS 链接以在网络https://repl.it/repls/SinfulWhichSynergy中启动代码 在这里您可以测试your python regexps and practice with

答案 2 :(得分:0)

此答案仅使用简单的python函数,并尽量不要“ pythonic”,因为这可能会使初学者感到困惑。

基本上,它在带有@的句子中查找sentence.find('@'),该语句返回首次出现的'@'或-1的位置索引。 OP的问题中未提及的一件事是什么构成“ @word”-更重要的是它在哪里停止。我添加了WORD_END常量来容纳所有表示单词结尾的字母。因此,该函数从第一个@WORD_END中的第一个字符中找到一个“ @word”。

要注意的另一点是,没有测试用例,句子中没有'@'。

#! /usr/bin/env python3

TESTS=['@VirginAmerica it was amazing, and arrived an hour early',
        'heyyyyy@VirginAmerica , am I dreaming?',
        'heyyyyy @VirginAmerica , am I dreaming?',
        '',
        '@United...',
        '@United@VirginAmerica',
        'no-at-word' ]

def removeMarkedWords(sentence):
    # A word ends with
    WORD_END=' \t\r\n,.;:<>?/+!@#$%^&*()|\}][{\"\'='
    result = ''

    # is there an @word?
    at_location = sentence.find('@')
    if ( at_location == -1 ):
        result = sentence
    else:
        while ( at_location != -1 ):
            if ( at_location > 0 ):
                result += sentence[0:at_location]  # keep the sentence prefix (before the '@')
                sentence = sentence[at_location:]  # remove the prefix
            else:
                # The sentence begins '@something...'
                # Find the end of the @word by finding the first non-word letter
                index = 1
                while ( index < len(sentence) and sentence[index] not in WORD_END ):
                    index += 1
                # trim off the @word (and throw it away)
                sentence = sentence[index:]
                #print( "DEBUG sentence = [" + sentence + "]" )
            # is there another @word?
            at_location = sentence.find('@')
            if ( at_location == -1 ):
                result += sentence  # no more @words, just keep the tail
    return result


for test in TESTS:
    print( "[%s]->[%s]" % ( test, removeMarkedWords( test ) ) )

给出结果:

[@VirginAmerica it was amazing, and arrived an hour early]->[ it was amazing, and arrived an hour early]
[heyyyyy@VirginAmerica , am I dreaming?]->[heyyyyy , am I dreaming?]
[heyyyyy @VirginAmerica , am I dreaming?]->[heyyyyy  , am I dreaming?]
[]->[]
[@United...]->[...]
[@United@VirginAmerica]->[]
[no-at-word]->[no-at-word]