0

我有许多包含旅行信息的电子表格。

我需要提取该行描述旅行的开始和结束位置,以及该行中的一两件事,但那些额外的字段应该不重要。

没有所有位置的已知列表,也没有固定的文本模式,我只能寻找位置名称。

我正在搜索的字段有 0-2 个位置,有时位置有别名。

问题

如果我们有这个:

00229 | 445 | RTF | Jan   |  trn_rtn_co  | Chicago to Base1 
00228 | 445 | RTF | Jan   |  train       | Metroline to home coming from Base1
00228 | 445 | RTF | Jan   |  train_s     | Standard train journey to Friends

例如,我(尽管会有所不同)会想要这个:

RTF|Jan|Chicago   |Base1
RTF|Jan|Home      |Base1
RTF|Jan|NULL      |Friends

然后继续,查找该人(其唯一 ID 为 RTF)的含义Base1Friends含义,并将其替换为合理的位置(假设他们只有一组“朋友”):

RTF|Jan|Chicago   |Rockford
RTF|Jan|Home      |Rockword
RTF|Jan|NULL      |Milwaukee

我需要的

我需要一种从最后一列中挑选关键词的方法,例如:Metroline to home come from Base1

我正在寻找三种类型的单词:

  1. 家庭位置
    这些是已知且有限的,我可以从列表中获取这些
  2. Home Aliases
    这些是已知且有限的,我可以从列表中获取这些
  3. 离开地点
    这些是未知的,但英国的城市/城镇/等我不知道如何在字符串中识别这些。这是我的主要问题

我的想法

我想到的程序是awk,但我不知道我是否可以可靠地搜索以找到将专有名词(即位置)用于位置名称的位置。

是否有标准位置的包、库或字典?

我可以得到一个程序来搜索电子表格并“学习”位置的名称吗?

这似乎是一个已经解决的问题(即在文本字符串中查找单词),但我不确定我在做什么,而且我只是一个新手程序员。

对我能做的任何帮助将不胜感激。

编辑:

任何答案,例如“US_Locations_Cities 是您可以检查的内容”、“使用...检查 awk 文件中提到的字符串”、“有一个语言 X 的库可以让程序学习识别位置名称,它是不是正则表达式,但它可能会起作用”,或者“这里有一个位置名称字典就可以了。

最终,任何可以帮助我做我想做的事情(即获取位置名称!)的东西都会很棒。

4

3 回答 3

3

很抱歉告诉你,但我认为这不是 100% 可编程的。最好的办法是定义一些标准搜索:

  • Chicago to Base1
    [WORD] to [WORD]:
    其中“to”是固定的,您可以在前后查找一个单词。之前的词是你的来源和目标之后的词

  • Metroline to home 从 Base1
    [WORD] 到 [WORD] 来自 [WORD]:
    其中“to”和“coming from”是固定的,您在适当的插槽中查找三个单词。

  • ETC

如果您可以匹配源和目标-> 好的
,如果您无法匹配某些内容,则为该行抛出错误并让用户决定甚至更好地实施适当的更正,并让程序自动重新评估该行。

这些都是不平凡的目标。考虑:

  • 我们的城市
  • 非英文文本条目
  • 缩写

对于自动纠错,请尝试将找到的 [WORD] 与我们或其他城市的列表相匹配。如果未找到城市,则抛出错误。如果您发现该错误,请将未找到的城市包含在您的城市列表中,或者将城市名称翻译为公开(官方)名称。

于 2012-08-17T12:04:49.447 回答
1

我可以建议的最好的方法是,只要您的位置都是美国城市,您就可以使用邮政编码数据库,例如这个

我不知道您希望任何程序如何获取诸如FriendsBase1

于 2012-08-17T13:08:03.357 回答
1

我必须同意 hacktick 的观点,就目前而言,它是不可编程的。似乎唯一的解决方案是发明一种语言或协议。

我认为一个简单的实现如下:

  1. 在这种语言中,您有两个关键字:toand from(您也可以将其分配at为关键字同义词from)。
  2. 这些关键字定义了字符串的一部分,作为识别名称的“扫描区域”

我只计划实施最简单的扫描,但如帖子末尾所示,您可以进行后备。

  1. 在实现中,您有一个“首选名称”哈希,您可以在其中定义要为那里出现的事物显示的名称。

    { Base1   => 'Rockford'
    , Friends => 'Milwaukee'
    , ...
    }
    
  2. 您可以split使用以下规则通过关键字之间的文本块来造句:

    A. 第一个块,如果不是关键字,则作为 'from' 的值。A. 在这个或任何后续块上,如果关键字则保存该值
    之后下一个块。A. 每个值在被存储为值之前都被“扫描”为首选短语。

    my @chunks 
        = grep {; defined and ( s/^\s+//, s/\s+$//, length ) } 
          split /\b(from|to)\s+/i, $note
        ;
    my %parts = ( to => '', from => '' );
    my $key;
    do { 
        last unless my $chunk = shift @chunks;
        if ( $key ) { 
            $parts{ $key } = $preferred_title{ $chunk } // $chunk;
            $key = '';
        }
        elsif ( exists $parts{ lc $chunk } ) { 
            $key = lc $chunk;
        }
        elsif ( !$parts{from} ) { 
            $parts{from} = $preferred_title{ $chunk } // $chunk;
        }
    } while ( @chunks );
    say join( '|', $note, @parts{ qw<from to> } );
    

至少,收集这些值并将它们打印出来可以给你一个筛子来决定进一步的行动方案。这将告诉您'home coming' 被视为 'from' 语句,以及'Standard train journey'.

您*可以'home coming'通过修改正则表达式来修复:

 /\b(?:(?:coming )?(from)|(to))\s+/i

我们可以将以下键值对添加到我们的首选标题哈希中:

home => 'Home'

我们可以简单地定义'Standard train journey' => '',或者我们可以创建一个拒绝模式列表,在其中我们拒绝一个字符串作为一个有意义的值,如果它们符合一个模式。

但是它们允许您转储值列表并优化您的数据扫描。另一个想法是,您似乎与您对地方的大写字母(“家”除外)的使用非常一致。所以我们可以通过将块与

/\b(home|\p{Upper}.*)/

请注意,这仍然认为'Standard train journey'是一个合适的位置。所以这仍然需要通过拒绝规则来处理。

在这里我重申,这可能是一种扫描数据的最小方法,以便您可以理解该系统需要什么作为位置并将其“80/20”下来:也就是说,希望这些规则能够处理 80%这些情况,您可以调整算法以处理剩余 20 个中的 80%,并迭代到最坏情况下您只需更改少数条目即可。

然后,您有一个规范,从那时起您在创建旅行笔记时需要遵循该规范。您甚至可以在输入笔记时对其进行扫描并提醒类似“在笔记中未找到目的地!”之类的信息。

于 2012-08-17T15:16:20.347 回答