Найти уникальные символы в файле - PullRequest
15 голосов
/ 23 декабря 2008

У меня есть файл с 450 000+ строк записей. Каждая запись имеет длину около 7 символов. То, что я хочу знать, это уникальные символы этого файла.

Например, если бы мой файл был следующим:

Entry
-----
Yabba
Dabba
Doo

Тогда результат будет

Уникальные символы: {abdoy}

Заметьте, меня не волнует дело, и мне не нужно заказывать результаты. Что-то подсказывает мне, что это очень легко решить людям с Linux.

Обновление

Я ищу очень быстрое решение. Я действительно не хочу создавать код для цикла по каждой записи, цикла по каждому символу ... и так далее. Я ищу хорошее решение сценария.

Обновление 2

Под Быстро я имею в виду быстрое внедрение ... не обязательно быстрое выполнение.

Ответы [ 21 ]

1 голос
/ 23 декабря 2008

Хотя это не сценарий, эта Java-программа сделает всю работу. Легко понять быстро (запустить)

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, {, |, }]
0 голосов
/ 19 ноября 2010
s=open("text.txt","r").read()
l= len(s)
unique ={}
for i in range(l):
 if unique.has_key(s[i]):
  unique[s[i]]=unique[s[i]]+1
 else:
  unique[s[i]]=1
print unique
0 голосов
/ 23 декабря 2008

Ну, друг мой, я думаю, это то, что вы имели в виду .... По крайней мере, это версия Python !!!

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 МБ (в зависимости от вашей оперативной памяти), но для более коротких файлов это весело:)

Я также должен добавить свою последнюю атаку !!!! По общему признанию, я исключил две строки, используя стандартный ввод вместо файла, я также уменьшил активный код с 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
0 голосов
/ 03 января 2009

Этот ответ вышеупомянутый, используя словарь.

Если это так, представленный там код можно немного упростить, поскольку в документации Python указано:

Лучше всего думать о словаре как неупорядоченный набор пар ключ-значение, с требованием, чтобы ключи уникальный (в пределах одного словаря) .... Если вы храните с помощью ключа, который уже в использовании, старое значение, связанное с этот ключ забыт.

Следовательно, эту строку кода можно удалить, поскольку ключи словаря всегда будут уникальными:

    if character not in letters:

И это должно сделать это немного быстрее.

0 голосов
/ 23 декабря 2008

Быстрое и грязное решение с использованием grep (при условии, что имя файла «file»):

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)

0 голосов
/ 23 декабря 2008

Python без использования набора.

file = open('location', 'r')
letters = []
for line in file:
    for character in line:
        if character not in letters:
            letters.append(character)
0 голосов
/ 23 декабря 2008

Где C:/data.txt содержит 454 863 строки из семи случайных буквенных символов, следующий код

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<br> mytojevqlgbxsnidhzupkfawr<br> c<br> 889<br> Press any key to continue . . .

В первой строке вывода указано количество байтов в C:/data.txt (454 863 * (7 + 2) = 4 093 767 байтов). Следующие две строки вывода - это уникальные символы в C:/data.txt (включая символ новой строки). В последней строке вывода указывается количество миллисекунд, которые код выполнял на Pentium 4 с тактовой частотой 2,80 ГГц.

0 голосов
/ 23 декабря 2008

Попробуйте этот файл с JSDB Javascript (включает механизм JavaScript в браузере Firefox):

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(''));
0 голосов
/ 23 декабря 2008

C раствор. По общему признанию это не самое быстрое решение для кода в мире. Но так как он уже закодирован и может быть вырезан и вставлен, я думаю, что он считается «быстрым для реализации» для плаката :) На самом деле я не видел каких-либо C-решений, поэтому я хотел опубликовать одно для чистого садистского удовольствия :)

#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;
}
0 голосов
/ 23 декабря 2008

в c ++ я сначала перебрал бы буквы в алфавите, а затем запустил strchr () для каждого файла в виде строки. это скажет вам, если это письмо существует, а затем просто добавьте его в список.

...