选择给定字符串中给定索引周围的单词


20

在Windows中,当您双击文本时,将选中文本中光标周围的词。

(此功能具有更复杂的属性,但对于此挑战无需实施。)

例如,让|您成为的光标abc de|f ghi

然后,当您双击时,def将选择子字符串。

输入输出

您将得到两个输入:一个字符串和一个整数。

您的任务是返回由整数指定的索引周围的字符串的单词子字符串。

您的光标可以在指定索引的字符串中的字符之前之后

如果您之前使用,请在答案中指定。

规格(规格)

索引保证在单词内,因此不会出现诸如abc |def ghi或的边缘情况abc def| ghi

该字符串将包含可打印的ASCII字符(从U + 0020到U + 007E)。

单词“ word”由regex定义(?<!\w)\w+(?!\w),其中\w[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]或“ ASCII中的字母数字字符(包括下划线)”定义。

索引可以是1索引 0索引。

如果您使用0索引,请在答案中指定。

测试用例

测试用例是1索引的,并且光标位于指定的索引之后

光标位置仅用于演示目的,不需要输出。

string    index     output    cursor position
abc def   2         abc       ab|c def
abc def   5         def       abc d|ef
abc abc   2         abc       ab|c abc
ab cd ef  4         cd        ab c|d ef
ab   cd   6         cd        ab   c|d
ab!cd     1         ab        a|b!cd

2
字符串可以包含换行符吗?
orlp

@orlp对该挑战进行了编辑,以将输入限制为可打印的ASCII,因此输入将不包含换行符。
FryAmTheEggman

您的测试用例除空格外不包含任何其他定界符。什么样的单词we're呢?
orlp

2
应该"ab...cd", 3返回什么?
泰特斯

5
@Titus“的索引被保证是一个字内”
马丁安德

Answers:


10

V10,9 7字节

À|diwVp

在线尝试!

此答案使用基于1的索引。

如果我们完全按照标题的说明进行操作,则可能会更短一些:“ 选择字符串中给定索引周围的单词”。我们可以做

À|viw

从字面上选择单词,但是不幸的是根本没有改变输出。因此,我们需要一些解决方法以使其工作,方法是将其切成一个寄存器,删除其余文本,然后将其粘贴回去。

说明:

À|          " Jump the position of argument 1
  diw       " (d)elete (i)nside this (w)ord.
     V      " Select this line
      p     " And replace it with the word we just deleted

5

C,104字节

p[99];i,d;main(l){for(scanf("%d",&i);scanf("%[^a-zA-Z0-9_]%[a-zA-Z0-9_]%n",&d,&p,&l),i>l;i-=l);puts(p);}

期望在stdin上的输入是从0开始的索引,后跟一个空格或换行符,然后是字符串。一个单词的最大长度为99个字符。例如:

2 abc def

看到C和perl绑在基于字符串的挑战上真的很酷。:D
DJMcMayhem

输入的字符串可以超过100个字符吗?
Leaky Nun

@LeakyNun是的,但是一个单词不能超过100个字符。
orlp

您是否想在要求中加入这一要求?
Leaky Nun

@DrGreenEg​​gsandIronMan太糟糕了,我不得不解决我的问题,因为它在
空白处

4

C(gcc),94个字节

f(n,p)char*p;{for(p+=n-1;isalnum(*p)|*p==95&&n--;--p);for(;isalnum(*++p)|*p==95;putchar(*p));}

零索引,定义一个使用索引,然后是字符串的函数。


我认为isalnum(*++p)|*p==95是未定义的行为。
owacoder

@owacoder是的,但是重要的是gcc吐出了一个可执行的可执行文件。*++p^95?isalnum(*p):1是更长的一个字节,但适用于每个编译器。
orlp

我认为领导空间是一个错字?另外,这是一个懒惰的IDEone链接。
FryAmTheEggman

isalnum(*++p)||*p==95也可以,增加一个字节。
owacoder

@FryAmTheEggman是的,现在修复。
orlp

3

视网膜22

(1)+¶(?<-1>。)* \ b | \ W. +

在线尝试!验证所有测试用例。常规程序将光标位置放在一元位置,然后是换行符,然后是字符串。\为了方便起见,测试套件还有其他代码可以在每行模式下运行,并使用a 作为分隔符,并使用十进制。

使用平衡组查找光标位置,然后回溯到单词边界。删除单词之前的单词,然后删除单词之后的单词。


2

C,115字节

函数f()需要字符串和索引(1索引)作为参数,并将结果打印到stdout。光标应在指定字符之后。

f(char*p,int n){char*s=p+n;for(;s>=p&&isalnum(*s)+(*s==95);--s);for(p=s+1;*p&&isalnum(*p)+(*p==95);putchar(*p++));}

2

JavaScript(ES6),57个字节

f=(s,n)=>s.slice(0,n).match(/\w*$/)+s.slice(n).match(/\w*/)

只需在光标点处对字符串进行切片(在0索引字符之前,其效果与在1索引字符之后相同),然后提取并连接相邻的单词片段。当光标位于单词的开始,结尾或不远处时,甚至返回有意义的结果。


在最后一个正则表达式中是否需要*?
查理·永利

@CharlieWynn是的,否则第二个测试用例只会返回de
尼尔

哎呀,我运气不佳
Charlie Wynn

2

Java 8,86 78字节

(s,p)->{for(String t:s.split("\\W"))if((p-=t.length()+1)<0)return t;return"";}

不用测试用例:

class Indexer {
    public static String f(String s, int p) {
        for(String t : s.split("\\W"))
            if((p -= t.length()+1) < 0)
                return t;
        return "";
    }

    public static void main(String[] args) {
        System.out.println(f("abc def",2));
        System.out.println(f("abc def",5));
        System.out.println(f("abc abc",2));
        System.out.println(f("ab cd ef",4));
        System.out.println(f("ab   cd",6));
        System.out.println(f("ab!cd",1));
    }
}

用非字母数字字符分割字符串,然后继续从指定位置减去每个子字符串的长度加1,直到变为负数为止。由于任何重复的非字母数字都表示为空字符串,因此减法逻辑非常容易。

该代码未经广泛测试,因此我想看看是否有人可以破解它。另外,考虑到这是Java代码,这不是最长的答案吗?:P


我知道已经快三年了,但是(s,p)->可以s->p->使用一个易变的lambda表达式(即java.util.function.Function<String, java.util.function.Function<String, String>> f)。此外,如果切换到Java 10,现在String就可以var了,尽管当时还不可用。无论如何,不​​错的答案。我看到我已经在过去的某个地方对其进行了更新。:)
Kevin Cruijssen



2

Pyke,19个字节

#Q;cjmli<i+s)lttjR@

在这里尝试!

用途Q;为空操作,以确保第一输入正确地放置

#          )   -  first where
   c           -       input.split()
    ml         -      map(len, ^)
      i<       -     ^[:i]
        i+     -    ^+[i]
          s    -   sum(^)
            lt - len(^)-2

单击您的链接时出现504错误。
Leaky Nun

@LeakyNun是的,我在写的时候无意中杀死了它,这就是为什么我拥有localhost链接的原因,它会回来的
Blue Blue


1
您的程序似乎正在输出N,其中第N个单词是所选单词,但是我们需要完整的单词
Value Ink 2016年

2

Python 2,70 66字节

import re
f=lambda x,y,r=re.split:r('\W',x[:y])[-1]+r('\W',x[y:])[0]

用非单词分隔符分割字符串,一次是在原始字符串上直到游标索引,然后是从游标索引处开始的字符串。返回左拆分的最后一个元素加上右拆分的第一个元素。感谢Leaky Nun节省了4个字节!


1

Clojure,92个字节

(fn[x k](let[[u i](map #(re-seq #"\w+"(apply str %))(split-at k x))](str(last u)(nth i 0))))

首先,将位置处的输入字符串k分成两个字符串。然后针对这些字符串查找"\w+",并将其作为列表返回。然后连接第一个列表的最后一个元素和第二个列表的第一个元素。

在线查看:https//ideone.com/Dk2FIs


1

JavaScript(ES6),52个字节

(s,n)=>RegExp(`^.{0,${n}}(\\W+|^)(\\w+)`).exec(s)[2]

const F = (s,n) => RegExp(`^.{0,${n}}(\\W+|^)(\\w+)`).exec(s)[2]

class Test extends React.Component {
    constructor(props) {
        super(props);
        const input = props.input || '';
        const index = props.index || 0;
        this.state = {
            input,
            index,
            valid: /\w/.test(input),
        };
    }
    onInput = () => {
        const input = this.refs.input.value;
        const index = Math.min(+this.refs.index.value, input.length);
        this.setState({
            input,
            index,
            valid: /\w/.test(input),
        });
    }
    render() {
        const {input, index, valid} = this.state;
        return (
            <tr>
                <td>{ this.props.children }</td>
                <td>
                    <input ref="input" type="text" onInput={this.onInput} value={input} />
                    <input ref="index" type="number" onInput={this.onInput} min="1" max={input.length} value={index} />
                </td> 
                {valid && [
                    <td>{F(input, index)}</td>,
                    <td><pre>{input.slice(0, index)}|{input.slice(index)}</pre></td>,
                ]}
            </tr>
        );
    }
}

class TestList extends React.Component {
    constructor(props) {
        super(props);
        this.tid = 0;
        this.state = {
            tests: (props.tests || []).map(test => Object.assign({
                key: this.tid++
            }, test)),
        };
    }
    addTest = () => {
        this.setState({
            tests: [...this.state.tests, { key: this.tid++ }],
        });
    }
    removeTest = key => {
        this.setState({
            tests: this.state.tests.filter(test => test.key !== key),
        });
    }
    
    render() {
        return (
            <div>
                <table>
                    <thead>
                        <th/>
                        <th>Test</th>
                        <th>Output</th>
                        <th>Diagram</th>
                    </thead>
                    <tbody>
                        {
                            this.state.tests.map(test => (
                                <Test key={test.key} input={test.input} index={test.index}>
                                    <button onClick={() => this.removeTest(test.key)} style={{
                                        verticalAlign: 'middle',
                                    }}>-</button>
                                </Test>
                            ))
                        }
                    </tbody>
                    <tfoot>
                        <td/>
                        <td>
                            <button onClick={this.addTest} style={{
                                width: '100%',
                            }}>Add test case</button>
                        </td>
                    </tfoot>
                </table>
            </div>
        );
    }
}

ReactDOM.render(<TestList tests={[
    { input: 'abc def', index: 2 },
    { input: 'abc def', index: 5 },
    { input: 'abc abc', index: 2 },
    { input: 'ab cd ef', index: 4 },
    { input: 'ab   cd', index: 6 },
    { input: 'ab!cd', index: 1 },
]} />, document.body);
input[type="number"] {
  width: 3em;
}
table {
  border-spacing: 0.5em 0;
  border-collapse: separate;
  margin: 0 -0.5em ;
}
td, input {
    font-family: monospace;
}
th {
  text-align: left;
}
tbody {
  padding: 1em 0;
}
pre {
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


为什么(\\W+|^)不呢(\\W|^)
l4m2

1

卢阿,71岁 67字节

哇,Lua不是最长的解决方案!仍然落后python一个字节,但不知道如何打败它。索引从1开始。

感谢@LeakyNun提醒我存在string.match,节省了4个字节

g,h=...print(g:sub(1,h):match"[%a_]*$"..g:sub(h+1):match("[%a_]+"))

旧71

注意:解释仍基于此,因为它也适用于新的解释,但包含有关以下内容的一些附加信息 gmatch

g,h=...print(g:sub(1,h):gmatch"[%a_]*$"()..g:sub(h+1):gmatch"[%a_]*"())

说明

首先,我们将参数解压缩为gh因为它们短于arg[x]

g,h=...

然后,我们构造输出,它是光标之前和之后部分的结合。

字符串的第一部分是

g:sub(1,h)

我们想在该单词的末尾找到单词,所以我们使用函数 string.gmatch

:gmatch"[%a_]*$"

此模式匹配0..n时间是字符串末尾的字母+下划线字符集的时间。gmatch以函数的形式(使用闭包原理)返回其匹配列表上的迭代器,因此我们执行一次即可获得单词的第一部分

g:sub(1,h):gmatch"[%a_]*$"()

我们以相同的方式得到第二部分

g:sub(h+1):gmatch"[%a_]*"())

唯一的区别是我们不必指定要在字符串开头的匹配项(使用[^%a_]*),因为这将是迭代器在首次调用时返回的匹配项。


g:sub(h+1):match"^[%a_]*"
Leaky Nun

@LeakyNun完全忘记了match\ o / 的存在,节省了很多字节,谢谢
Katenkyo '16

-1为“索引”
Leaky Nun


我不在乎,“索引”仍为-1。
Leaky Nun

1

Javascript(使用外部库)(168字节)

(n,w)=> _.From(w).Select((x,i)=>({i:i,x:x})).Split((i,v)=>v.x==" ").Where(a=>a.Min(i=>i.i)<=n-1&&a.Max(i=>i.i)>=n-2).First().Select(i=>i.x).Write("").match(/^\w*^\w*/)[0]

链接到lib:https : //github.com/mvegh1/Enumerable/blob/master/linq.js

代码说明:库接受一个字符串,该字符串被解析为char数组。它被映射到一个存储索引和char的对象。每次出现“”时,该序列都会分为多个子序列。通过检查游标索引是否包含在子序列的最小索引和最大索引中来过滤子序列。然后我们取第一个子序列。然后我们转换回一个char数组。然后,我们用“”作为分隔符来连接所有字符。然后我们针对单词regex进行验证。然后我们进行第一场比赛。

在此处输入图片说明


单词“ word”由regex定义(?<!\w)\w+(?!\w),其中\w[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]或“ ASCII中的字母数字字符(包括下划线)”定义。
Leaky Nun

当我在regex101.com上对ab!cd运行该正则表达式时,我得到了:没有提取匹配组。这意味着您的模式匹配,但其中没有(捕获(组))与主题字符串中的任何内容匹配。也许我在某个地方犯了一个错误...
applejacks01 '16

为什么我需要捕获任何东西?
Leaky Nun

我知道这不是学习的地方,但是我说的是,当我对ab!cd运行该正则表达式时,我什么也没得到。那么,为什么“ ab”将是正确的输出?
applejacks01 2016年


1

Perl 6,34个字节

->\b{&{first *.to>b,m:g/<<\w+>>/}}

在线尝试!

接受输入的匿名代码块,例如f(n)(string)

说明:

->\b{                            }   # Anonymous code block that takes a number
     &{                         }    # And returns another code block that
       first       ,m:g/<<\w+>>/     # Finds the first word in the input
             *.to>b                  # Where the start is after the number


1

APL(NARS),58个字符,116个字节

{m←⎕A,⎕a,⎕D,'_'⋄↑v⊂⍨m∊⍨v←⍵↓⍨¯1+⍵{⍵≤1:⍵⋄m∊⍨⍵⊃⍺:⍺∇⍵-1⋄⍵+1}⍺}

⍵{⍵≤1:⍵⋄m∊⍨⍵⊃⍺:⍺∇⍵-1⋄⍵+ 1}⍺查找字符串的起始位置...如何使用和测试:

  f←{m←⎕A,⎕a,⎕D,'_'⋄↑v⊂⍨m∊⍨v←⍵↓⍨¯1+⍵{⍵≤1:⍵⋄m∊⍨⍵⊃⍺:⍺∇⍵-1⋄⍵+1}⍺}
  2 f 'abc def'
abc
  5 f 'abc def'
def
  2 f 'abc abc'
abc
  4 f 'ab cd ef'
cd
  1 f 'ab!cd'
ab
  6 f 'ab   cd'
cd 

0

MATL16 15字节

'\w+'5B#XXi>)1)

游标以1为索引,并且在字符之后(如在测试用例中一样)。

在线尝试!验证所有测试用例

'\w+'    % Push string to be used as regex pattern
5B#XX    % Take input string implicitly. Apply regex. Push matches and ending indices
i>       % Take input number. Compare with obtained ending indices. Gives true for
         % ending indices that exceed the input number
)        % Use as logical index to select the corresponding matches
1)       % Select the first match. Implicitly display

0

PowerShell v3 +,103101字节

param($a,$n)for(;$n[++$a]-match'\w'){}$i=$a--;for(;$n[--$a]-match'\w'-and$a-ge0){}-join$n[++$a..--$i]

有点愚蠢的解决方案,但是与其他解决方案不同。

将输入$a作为字符串从0开始的索引$n。然后,我们找到了单词的边界。虽然我们尚未到达字符串的末尾和/或仍在匹配单词字符,但是我们++$a。然后,由于设置了栅栏,我们进行了设置$i=$a--。接下来,我们向后爬取,递减$a直到它0达到或者达到非单词字符。然后,我们基于这两个边界(对OBOE进行一些增减来对输入字符串进行切片),并将-join其一起产生结果。

例子

PS C:\Tools\Scripts\golfing> .\select-the-word-around-the-index.ps1 2 'This!test'
This

PS C:\Tools\Scripts\golfing> .\select-the-word-around-the-index.ps1 5 'This!test'
test

select-the-word-around-the-index.ps1
Leaky Nun

0

PHP,98字节

function f($s,$p){foreach(preg_split('#\W+#',$s,-1,4)as$m)if($m[1]+strlen($m[0])>=$p)return$m[0];}
  • 用非单词字符分割字符串,记住它们的位置(4== PREG_SPLIT_OFFSET_CAPTURE),循环遍历单词直到到达位置。
  • PHP字符串的索引为0,光标在字符之前,但可以在单词之前或之后

0

Python 3中,112 140个字节

from string import*
p='_'+printable[:62]
def f(s,h,r=''):
 while s[h]in p and h>-1:h-=1
 while h+1<len(s)and s[h]in p:h+=1;r+=s[h]
 return r

0索引。

从索引后退到第一个字母数字字符,然后前进到索引后的最后一个字母数字字符。可能有一种更聪明的方法可以做到这一点。

试试吧


_添加了@LeakyNun ,我不确定为什么会出现错误f('abc',1)
气象学家,2016年

0

JavaScript(ES 6), 43 42字节

s=>n=>s.replace(/\w*/g,(x,y)=>y<n?s=x:0)&&s

JavaScript(ES 3),65个字节

function(s,n){s.replace(/\w*/g,function(x,y){y<n?s=x:0});alert(s)}

0

05AB1E,14 个字节

ð«._DžjмS¡Á2£J

@AndersKaseorg的Pyth答案端口

像挑战测试用例一样被1索引。

在线尝试验证所有测试用例

说明:

ð«              # Append a space to the (implicit) input-String
  ._            # Rotate this string the (implicit) input-integer amount of times
                #  towards the left
     D          # Duplicate this string
      žjм       # Remove [a-zA-Z0-9_] from the string
         S¡     # Split the rotated string by each of the remaining characters
           Á    # Rotate the resulting list once towards the right
            2£J # And only leave the first two items, joined together
                # (which is output implicitly)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.