我有一个包含450,000+条目行的文件。每个条目的长度约为7个字符。我想知道的是此文件的唯一字符。
例如,如果我的文件是以下文件;
Entry ----- Yabba Dabba Doo
然后结果将是
[唯一字符:{abdoy}
注意,我不在乎大小写,也不需要订购结果。有些东西告诉我,这对于Linux人员来说很容易解决。
我正在寻找一个非常快速的解决方案。我真的不想创建代码来遍历每个条目,遍历每个字符...等等。我正在寻找一个不错的脚本解决方案。
通过快速,我的意思是快速实施...不一定快速运行。
gc file.txt | select -Skip 2 | % { $_.ToCharArray() } | sort -CaseSensitive -Unique
产生:
Dÿ一种bo
我喜欢它很容易阅读。EDIT:这是一个更快的版本:
$letters = @{} ; gc file.txt | select -Skip 2 | % { $_.ToCharArray() } | % { $letters[$_] = $true } ; $letters.Keys
counts个唯一字符。仅在最后省略sed "s/./\l\0\n/g" inputfile | sort -u | grep -vc ^$
EDIT抱歉,我实际上误解了这个问题。上面的代码
c
开关显然可以解决问题,但是,此解决方案对saua的解决方案没有真正的优势(特别是因为他现在使用相同的sed
模式而不是显式捕获)。
import java.util.*;
import java.io.*;
public class Unique {
public static void main( String [] args ) throws IOException {
int c = 0;
Set s = new TreeSet();
while( ( c = System.in.read() ) > 0 ) {
s.add( Character.toLowerCase((char)c));
}
System.out.println( "Unique characters:" + s );
}
}
您将这样调用它:
type yourFile | java Unique
或
cat yourFile | java Unique
例如,此问题的HTML中的唯一字符是:
Unique characters:[ , , , , !, ", #, $, %, &, ', (, ), +, ,, -, ., /, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, :, ;, <, =, >, ?, @, [, \, ], ^, _, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, {, |, }]
var seenAlreadyMap={};
var seenAlreadyArray=[];
while (!system.stdin.eof)
{
var L = system.stdin.readLine();
for (var i = L.length; i-- > 0; )
{
var c = L[i].toLowerCase();
if (!(c in seenAlreadyMap))
{
seenAlreadyMap[c] = true;
seenAlreadyArray.push(c);
}
}
}
system.stdout.writeln(seenAlreadyArray.sort().join(''));
file = open('location.txt', 'r')
letters = {}
for line in file:
if line == "":
break
for character in line.strip():
if character not in letters:
letters[character] = True
file.close()
print "Unique Characters: {" + "".join(letters.keys()) + "}"
#include<stdio.h>
#define CHARSINSET 256
#define FILENAME "location.txt"
char buf[CHARSINSET + 1];
char *getUniqueCharacters(int *charactersInFile) {
int x;
char *bufptr = buf;
for (x = 0; x< CHARSINSET;x++) {
if (charactersInFile[x] > 0)
*bufptr++ = (char)x;
}
bufptr = '\0';
return buf;
}
int main() {
FILE *fp;
char c;
int *charactersInFile = calloc(sizeof(int), CHARSINSET);
if (NULL == (fp = fopen(FILENAME, "rt"))) {
printf ("File not found.\n");
return 1;
}
while(1) {
c = getc(fp);
if (c == EOF) {
break;
}
if (c != '\n' && c != '\r')
charactersInFile[c]++;
}
fclose(fp);
printf("Unique characters: {%s}\n", getUniqueCharacters(charactersInFile));
return 0;
}
for char in a b c d e f g h i j k l m n o p q r s t u v w x y z; do
if [ ! -z "`grep -li $char file`" ]; then
echo -n $char;
fi;
done;
echo
我本来可以把它做成单线的,但只想使其易于阅读。
((编辑:忘记了-i切换到grep)
f = open("location.txt", "r") # open file
ll = sorted(list(f.read().lower())) #Read file into memory, split into individual characters, sort list
ll = [val for idx, val in enumerate(ll) if (idx == 0 or val != ll[idx-1])] # eliminate duplicates
f.close()
print "Unique Characters: {%s}" % "".join(ll) #print list of characters, carriage return will throw in a return
它不会遍历每个字符,它也相对较短。您不希望用它打开500 MB的文件(取决于您的RAM),但是对于较短的文件,这很有趣:)
我还必须添加我的最终攻击!!!!诚然,我通过使用标准输入而不是文件消除了两行,我还将活动代码从3行减少到2行。基本上,如果我用上面一行的表达式替换了打印行中的ll,那么我本来可以有1行的活动代码和一行导入代码...无论如何,我们现在很开心:)
import itertools, sys # read standard input into memory, split into characters, eliminate duplicates ll = map(lambda x:x[0], itertools.groupby(sorted(list(sys.stdin.read().lower())))) print "Unique Characters: {%s}" % "".join(ll) #print list of characters, carriage return will throw in a return
最好将字典视为无序键集:值对,要求钥匙是唯一的(在一本字典内)...您使用已经存在的密钥进行存储在使用中,与那个钥匙被忘记了。
因此,可以删除此行代码,因为字典键始终始终是唯一的:
if character not in letters:
这应该使它更快一些。
using System;
using System.IO;
using System.Collections;
using System.Diagnostics;
namespace ConsoleApplication {
class Program {
static void Main(string[] args) {
FileInfo fileInfo = new FileInfo(@"C:/data.txt");
Console.WriteLine(fileInfo.Length);
Stopwatch sw = new Stopwatch();
sw.Start();
Hashtable table = new Hashtable();
StreamReader sr = new StreamReader(@"C:/data.txt");
while (!sr.EndOfStream) {
char c = Char.ToLower((char)sr.Read());
if (!table.Contains(c)) {
table.Add(c, null);
}
}
sr.Close();
foreach (char c in table.Keys) {
Console.Write(c);
}
Console.WriteLine();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
}
}
产生输出
4093767 mytojevqlgbxsnidhzupkfawr c 889 Press any key to continue . . .
输出的第一行告诉您
C:/data.txt
中的字节数(454,863 *(7 + 2)= 4,093,767字节)。输出的后两行是C:/data.txt
中的唯一字符(包括换行符)。输出的最后一行告诉您代码在2.80 GHz Pentium 4上执行所需的毫秒数。
while read -n 1 char; do echo "$char"; done < entry.txt | tr [A-Z] [a-z] | sort -u
UPDATE:仅此而已,因为我很无聊并且仍然在考虑这个问题,所以这里是一个使用set的C ++版本。如果运行时间很重要,那么这将是我推荐的选项,因为C ++版本需要花费超过半秒的时间来处理具有450,000+条目的文件。请注意,我忽略空格,并且根据要求不区分大小写。
#include <iostream> #include <set> int main() { std::set<char> seen_chars; std::set<char>::const_iterator iter; char ch; /* ignore whitespace and case */ while ( std::cin.get(ch) ) { if (! isspace(ch) ) { seen_chars.insert(tolower(ch)); } } for( iter = seen_chars.begin(); iter != seen_chars.end(); ++iter ) { std::cout << *iter << std::endl; } return 0; }
对于450,000+的入口文件(chars.txt),这是示例运行时间:
[user@host]$ g++ -o unique_chars unique_chars.cpp [user@host]$ time ./unique_chars < chars.txt a b d o y real 0m0.638s user 0m0.612s sys 0m0.017s
file = open('location', 'r')
letters = []
for line in file:
for character in line:
if character not in letters:
letters.append(character)
print(letters)
sed -e "s/./\0\n/g" inputfile | sort -u
这不是很好,它不是很快,并且输出也不完全是指定的,但是应该可以正常工作...
为了更加荒谬,我介绍了将输出转储到一行的版本:
sed -e "s/./\0\n/g" inputfile | sort -u | while read c; do echo -n "$c" ; done
#include <stdio.h>
int main(void)
{
int chars[256] = {0}, c;
while((c = getchar()) != EOF)
chars[c] = 1;
for(c = 32; c < 127; c++) // printable chars only
{
if(chars[c])
putchar(c);
}
putchar('\n');
return 0;
}
编译,然后执行
cat file | ./a.out
要获得file
中唯一可打印字符的列表。
s = open("data.txt", "r").read()
print "Unique Characters: {%s}" % ''.join(set(s))
带有设置的Python(具有更好的输出)
import re
text = open("data.txt", "r").read().lower()
unique = re.sub('\W, '', ''.join(set(text))) # Ignore non-alphanumeric
print "Unique Characters: {%s}" % unique
脚本到底是什么?
Python会做吗?
如果是,那么这是一种解决方案:
import sys;
s = set([]);
while True:
line = sys.stdin.readline();
if not line:
break;
line = line.rstrip();
for c in line.lower():
s.add(c);
print("".join(sorted(s)));
Create an array of unsigned ints, initialized to zero.
Iterate though the in memory file, using each byte as a subscript into the array.
increment that array element.
Discard the in memory file
Iterate the array of unsigned int
if the count is not zero,
display the character, and its corresponding count.