我正在尝试将文件转换为(key,value)对。 每行都以
给出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中执行此操作,但无法提出解决方案,除非我逐行读取文件并使用循环来执行此操作。 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
}
}
答案 0 :(得分:1)
在Python中,你可以使用list comprehension添加所谓的键/值对,如下所示:
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')]
你需要的是循环每一行(摆脱换行符和空格)并且 NOTHING 错误的循环行,抓住第一个元素作为“键”和对(如果任何)其余元素为“值”。
答案 1 :(得分:0)
首先,根据分隔符
分割你的行 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
关联的值。
答案 2 :(得分:0)
给出输入
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')]
答案 3 :(得分:0)
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
答案 4 :(得分:0)
这是一个无循环的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]]
,其中数组中的每个元素都是一个单词,迭代器中的每个元素都是该行的单词数组。
让我们以for-comprehension格式重写pairs
以更好地理解它。请注意,下面的内容将转换为与原始定义完全相同的命令:
def pairs = for {
line <- tokens
letter <- line.tail
} yield line.head -> letter
因此,对于每一行以及该行的tail
中的每个字母,我返回一对该行的头部和该尾部。请记住,每一行都是该行中的一个单词数组。 line.head
将成为该行中的第一个单词,line.tail
是该行中的所有其他单词。因此,letter
将是所有单词,但第一个单词,这正是您所要求的。
回到原来的定义,flatMap
和map
之间的区别在于,flatMap
的结果是扁平的。
pairs
的类型为Iterator[(String, String)]
。如果我使用的是map
而不是flatMap
,则类型将为Iterator[Array[(String, String)]]
。