如何分割一条线并成对映射



我正在尝试将文件转换为(键,值)对。每行给出为

1 A B C D
2
3 E
4 F G

我想将它们配对为

(1,A),(1,B),(1,C),(1,D),(3,E),(4,F),(4,G)

试图在python/scala中做到这一点,但无法想出解决方案,除非我逐行读取文件并使用循环来做到这一点。斯卡拉的代码是:

val fileRDD = sc.textFile("input.txt")
val map = fileRDD.filter(_.split("t").length>1).map{
    line=>
    val fields = line.split("t")
    var i = 1;
    while(i<fields.length){
    (fields(0),fields(1))
    i=i+1
    }
}

在 Python 中,您可以使用列表推导添加所谓的键/值对,如下所示:

with open('your_file', 'r') as f:
    result = []
    for line in f:
        line = line.strip().split(' ')
        result += [(int(line[0]), x) for x in line[1:] if x]

result
[(1, u'A'),
 (1, u'B'),
 (1, u'C'),
 (1, u'D'),
 (3, u'E'),
 (4, u'F'),
 (4, u'G')]
您需要的是循环每行(

去掉换行符和空格),循环行没有任何问题,将第一个元素作为"键"抓取,并将其余元素配对(如果有的话)作为"值"。

这是一个无循环的 Scala 版本:

def source = scala.io.Source fromFile "input.txt"
def lines = source.getLines
def tokens = lines map (_ split "t")
def pairs = tokens flatMap (line => line.tail map (line.head -> _))
pairs.toList

source定义应该是显而易见的:我正在阅读Source

lines定义返回文件中行的Iterator[String]。请注意,使用后确实需要关闭source,我在这里不这样做。

我定义tokens来获取每行并拆分它。这将是一个Iterator[Array[String]],其中数组中的每个元素都是一个单词,迭代器中的每个元素都是该行的单词数组。

让我们以理解格式重写pairs以更好地理解它。请注意,下面将其转换为与原始定义完全相同的命令:

def pairs = for {
  line <- tokens
  letter <- line.tail
} yield line.head -> letter

因此,对于每一行,以及行tail中的每个字母,我返回一对行的头部和尾部。请记住,每一行都是该行中的单词数组。line.head将是该行中的第一个单词,line.tail该行中的所有其他单词。因此,letter将是除第一个单词之外的所有单词,这正是您所要求的。

回到最初的定义,flatMapmap之间的区别在于,嗯,flatMap的结果是扁平的。

pairs的类型是 Iterator[(String, String)] .如果我使用map而不是flatMap,则类型将是Iterator[Array[(String, String)]]

首先,根据分隔符拆分行

String[] pairs = input.split(" ");

然后,循环遍历您所做的拆分中的每个String,直到用完对

int index = 0;
while (index + 1 < pairs.length) {
    index += 2;
}

我们使用index+1因为我们想确保有一个键和一个值,而不仅仅是一个键。然后,如果有,请将它们添加到地图中。

map.put(pairs[index], pairs[index + 1]);

下面可以看到一个完整的示例。我使用了一行,但是如果您使用的是具有多行的文件,只需像下面一样分别处理每一行。

public static void main(String[] args) throws Exception {
    String input = "1 A B C D 2 3 E 4 F G";
    String[] pairs = input.split(" ");
    Map<String, String> map = new HashMap<String, String>();
    int index = 0;
    while (index + 1 < pairs.length) {
        map.put(pairs[index], pairs[index + 1]);
        index += 2;
    }
    for(Entry<String,String> en : map.entrySet()){
        System.out.println(en.getKey() + " : " + en.getValue());
    }
}

给我输出:

3 : E
D : 2
1 : A
B : C
4 : F

请注意如何跳过G,因为没有要与键G关联的值。

给定输入


1 A B C D
2
3 E 4 F G

您需要做的就是获取每行的数字和后续字符。然后拆分字符并为每个字符创建一个元组。

法典

import re
input = '''1 A B C D
2
3 E
4 F G'''
values = []
for line in input.split('n'):
    tokens = re.findall(r'^(d+) (.*)$', line)
    if len(tokens) == 1 and len(tokens[0]) == 2:
        for val in tokens[0][1].split(' '):
            values.append((int(tokens[0][0]), val))
print(values)

输出

[(1, 'A'), (1, 'B'), (1, 'C'), (1, 'D'), (3, 'E'), (4, 'F'), (4, 'G')]

file.txt

1 A B C D
2
3 E
4 F G

main.py

lines = open('file.txt').readlines() # open raw file
lines = [line.strip() for line in lines] # remove excess
lines = [line.split(' ') for line in lines] # split lines
pairs = []
for line in lines:
    key = int(line[0]) # number key
    for char in line[1:]:
        if len(lines) > 1:
            new = (key, char) # create new pair
            pairs.append(new) # add pair to list
print pairs

最新更新