2017-04-19 3 views
2

私は現在プロジェクトで作業しています。私の仕事は今ここでデバイスが2Gかどうかをバンドに基づいて指定する必要がありますBandsの列に記載されています。たとえば、それで特定のキーワードを文字列に入力してPythonのif文を作成する

Device ID |Bands|2G(New added column) 
123 |GSM 1800, GSM 700 |            
124 | GSM 1800, GSM 700, GSM 1, LTE TDD |        
125 | TD-SCDMA,1 SIM |            
126 |GSM850 (GSM800),WCDMA FDD Band I,WCDMA FDD Band VIII,2 SIM | 

コラム「バンド」は唯一の他、単語「GSM」、それは2Gですが含まれている場合、N.

私はreモジュールを使用して試してみましたが、私はいくつかで立ち往生していますポイント。私の質問が理解できない場合は

import re 
import csv 
... 
two_G_only = [] 
... 
with open('filepath.txt', "rU") as f: 
    reader = csv.DictReader(f, delimiter = "|") 
    for row in reader: 
     ... 
     ... 
     if 'GSM' in row['Bands']: 
     gsm_only = " ".join(re.findall("[a-zA-Z]+", row['Bands'])) 
     #Im stuck at here because I don't know how to test whether there is only GSM or else   
    else: 
     two_G_only.append('N') 
     ... 
     ... 

は、私はコメントしない、事前にありがとうござい結果

Device ID | Bands | 2G 
123 | GSM 1800, GSM 700 | Y 
124 |GSM 1800, GSM 700, GSM 1, LTE TDD | N 
125 |TD-SCDMA,1 SIM | N 
126 |GSM850 (GSM800),WCDMA FDD Band I,WCDMA FDD Band VIII,2 SIM|N 

ために何が必要です。私はすでにサイトで提供されているいくつかのソリューションを検索しましたが、質問される質問は同じ問題/概念ではないと確信しています。

答えて

0

データをタブまたはスペースで列に区切って表示しますが、区切り記号として縦棒(|)を使用していることをコードで示しています。どちらが正しいかはわかりませんが、それはあなたの問題です。

私が理解しているように、2番目の列のさまざまなサブフィールドをカンマで区切り、サブフィールドのそれぞれに「GSM」というテキスト文字列が含まれていれば1つの値(真)少なくとも1つのサブフィールドにその文字列が含まれていない場合は、別の値(false)を返すように指定することができます。右?

あなたの例では、あなたのcsvリーダーがreaderであるとしましょう。 for-row-inループは正しいです。これは、この計算をすべての行で個別に実行する必要があるためです。

for row in reader: 

そのループの中で、あなたがバンド列へのアクセスが必要です。

bands = row['Bands'] 

カンマでサブフィールドを分割する、のが基本str.split機能を使用できるように、サブフィールドを調べるために:

subfields = bands.split(',') 

ここで、その文字列のリストをブール値のリストに変換し、Pythonの組み込みのanyは、リスト全体を評価する関数です。私たちは、リスト内包でこれを行います。バンドのいずれかが「GSM」を含むように失敗した場合、それが一致します。

if any([ ('GSM' not in band) for band in subfields ]): 
     _2g_or_not_2g = 'N' 

    else: 
     _2g_or_not_2g = 'Y' 

このif文、それが言う大まかに行います。

このコードを書く方法はいくつかあります。たとえば、Python all関数を使用して、否定的なテストを肯定的なテストにすることができます。これは、if文の「意味」を逆転し、武器を切り替えるになります。

if all([ 'GSM' in band for band in subfields ]): 
     _2g_or_not_2g = 'Y' 
    else: 
     _2g_or_not_2g = 'N' 

また、あなたは小さなリストにダウンリストをフィルタリングするために、リスト内包表記に... if condition修飾子を使用することができます。

最後に、もちろん、あなたがお互いに表現をマージし始めることができます - すべての行でそれに気づくために、実際の分割式でsubfieldsを置き換える、など

+0

私はそう、私はタブまたはスペースに区切られたパイプから元のデータを変更することが読みやすくしたかったので、実際には私のせいですdelimited.Questionが編集されました。 – yunaranyancat

0

一つのことを、バンドはそれぞれカンマで区切られます。
これを利用できます。
関数split()は、その行の文字列のリストを提供します。各行には、単一のバンドの名前が含まれています。

問題がはるかに簡単です。個々のバンドに「GSM」という部分文字列がない場合、その行は失格となります。「N」を返します。
その行のどのバンドも失格になっていない場合(つまり、名前にGSMが含まれている場合)は、その行に 'Y'を返します。

find()関数を使用して、文字列に指定された部分文字列が含まれているかどうかを確認できます。
たとえば、'LTE TDD'.find('GSM')は値-1を返します。

デバイスIDを削除する必要はなく、最初のバンドを含むアイテムの一部にすることもできます。それを単純にしておきたいのは、特定の行のテキスト(쉼표で区切られた)のすべての部分に「GSM」という部分文字列が含まれているかどうかだけです。

def is_GSM(bands): 
    for band in bands: 
     if (band.find('GSM') = -1: 
      return('N') 
    return('Y') 

for row in reader: 
    bands = row.split(',')    
    two_G_only.append(is_GSM(bands)) 

`` `

def is_GSM(bands): 
    for band in bands: 
     if (band.find('GSM') = -1: 
      # "GSM" wasn't in the band name 
      return('N') 

    # we looked at all the bands, and did not find a disqualifier.. 
    # This row must be "GSM' only 2G bands. 
    return('Y') 

for row in reader: 
    # not needed: first strip off the device_id in this row's string. 
    # row = row[3:] 

    bands = row.split(',') 
    # ie: bands = ['124 GSM 1800', ' GSM 700', ' GSM 1', ' LTE TDD'] 

    # send this list to is_GSM(), and append the result     
    two_G_only.append(all_are_GSM(bands)) 

` ``

関連する問題