3

我有一个任意偶数项目的列表。

输入数据:

Red
Orange
Yellow
Green
Blue
Violet

输出数据:

Red -> Violet
Violet -> Orange
Orange -> Blue
Blue -> Yellow
Yellow -> Green
Green -> Red

这个想法是最高的项目与最低的项目匹配,我想有点从堆栈的两端弹出东西。一旦堆栈用完,剩下的最后一场比赛就是我们开始的比赛。

我从这个开始:

awk '{a[NR]=$0} END {for (i=1;i<=NR;i++) {printf("%s -> %s\n",a[i],a[NR-i+1])}}'

它从上到下匹配,但不会“弹出”。

这在awk中可能吗?

注意:我已标记此“python”,因为虽然我不知道如何在 python 中执行此操作,但我非常知道,如果它比 awk 答案更优雅,我会接受 python 答案。:-)

4

7 回答 7

5

这是一个 Python 解决方案:

data = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Violet']
first = data[0]
while data:
    a, b = data[0], data[-1]
    data = data[1:-1]
    print '{} -> {}'.format(a, b)
    print '{} -> {}'.format(b, data[0] if data else first)

这里的起点是数据列表,如果您需要从文件中读取输入,您可以使用以下内容来填充data

data = [line.strip() for line in open(filename)]

如果要从标准输入读取数据,可以使用以下命令:

import sys
data = [line.strip() for line in sys.stdin]

为了有效地从列表的开头和结尾删除,请使用collections.deque。如果您从标准输入读取,这将是这样的:

import sys
import collections

data = collections.deque(line.strip() for line in sys.stdin)
first = data[0]
while data:
    a, b = data.popleft(), data.pop()
    print '{} -> {}'.format(a, b)
    print '{} -> {}'.format(b, data[0] if data else first)
于 2012-11-27T21:03:24.443 回答
2

在我看来,您想逐个遍历输入数据。

根据您的代码,这是 awk 的开始:

[ghoti@pc ~]$ awk '{a[NR]=$0} END {for (i=2;i<=NR;i+=2) {printf("%-10s -> %s\n",a[i/2],a[NR-i/2+1]); printf("%-10s -> %s\n",a[NR-i/2+1],a[i/2+1]);}}' colours
Red        -> Violet
Violet     -> Orange
Orange     -> Blue
Blue       -> Yellow
Yellow     -> Green
Green      -> Green

当然,这不处理最后一行中的“换行”情况。为此,我们可以稍微扩展一下代码。在这里,不再是 1-liner:

{a[NR]=$0}

END {
  for (i=2;i<NR;i+=2) {
    printf("%-10s -> %s\n",a[i/2],a[NR-i/2+1]);
    printf("%-10s -> %s\n",a[NR-i/2+1],a[i/2+1]);
  }
  printf("%-10s -> %s\n",a[i/2],a[NR-i/2+1]);
  printf("%-10s -> %s\n",a[NR-i/2+1],a[1]);
}

注意 final 的最后一个选项的区别printf()

于 2012-11-27T21:04:21.657 回答
1

由于您更喜欢 awk 解决方案,请尝试以下解决方案:

awk '{a[NR]=$0}END{
for (i=1;i<=NR;i++){
    t=NR-i+1;
    print a[i]"->"a[t]
    if(t!=i+1)
        print a[t]"->"a[i+1]
    else{
        print a[t]"->"a[1]
        exit;
    }
}
}' file

测试

kent$  cat test.txt
Red
Orange
Yellow
Green
Blue
Violet

kent$  awk '{a[NR]=$0}END{
for (i=1;i<=NR;i++){
        t=NR-i+1;
        print a[i]"->"a[t]
        if(t!=i+1)
                print a[t]"->"a[i+1]
        else{
                print a[t]"->"a[1]
                exit;
        }
}
}' test.txt
Red->Violet
Violet->Orange
Orange->Blue
Blue->Yellow
Yellow->Green
Green->Red
于 2012-11-27T21:24:43.140 回答
1

不是 awk 或 python 的答案,但你已经收到了很多。这是使用 GNU coreutils 和 sed 的一种方法。

看到第一列是列表的顶部和底部的混合,并且第二列是相同的,但是行向上旋转了一个,有几个习语会有所帮助。

混合顶部和底部的行,但只抓取列表的上半部分:

len=$(wc -l < colours)
paste -d '\n' colours <(tac colours) | head -n $len > colours.mixed

内容colors.mixed

Red
Violet
Orange
Blue
Yellow
Green

将行向上旋转一:

(tail -n+2 colours.mixed; head -n1 colours.mixed) > colours.mixed.rotated

输出:

Violet
Orange
Blue
Yellow
Green
Red

综合起来,这给出了预期的结果:

paste colours.mixed colours.mixed.rotated | sed 's/\t/ -> /'

结果:

Red -> Violet
Violet -> Orange
Orange -> Blue
Blue -> Yellow
Yellow -> Green
Green -> Red
于 2012-11-27T23:02:26.617 回答
0

没有任何 IO,但假设它colours作为列表加载,然后是 Python 解决方案(尽管它可以进行一些调整以使其更懒惰):

colours = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Violet']

from itertools import islice, chain, izip_longest

together = zip(colours, reversed(colours))
flattened = list(islice(chain.from_iterable(together), len(colours)))
for a, b in izip_longest(flattened, flattened[1:], fillvalue=flattened[0]):
    print '{} -> {}'.format(a, b)

Red -> Violet
Violet -> Orange
Orange -> Blue
Blue -> Yellow
Yellow -> Green
Green -> Red

要获得colours,您可以使用:

import sys
colours = [line.strip() for line in sys.stdin]
于 2012-11-27T21:30:06.977 回答
0

这是另一个python解决方案。注意,该项的值(i&1)是 i 的低位,(i<n-2)如果 i 小于 n-2,该项的值为 1,否则为 0。

s = ['Red', 'Orange', 'Yellow', 'Green', 'Blue', 'Violet']
n=len(s); j, k = 0, n-1
for i in range(n):
    print s[j], s[k]
    j, k = k, (n-k-(i&1))*(i<n-2)
于 2012-11-27T21:44:28.187 回答
0

我对您要执行的操作感到非常困惑,因为您的起点似乎是一个脚本,它可以准确地产生您发布的所需输出!

显然我错过了一些东西,但这是你正在寻找的东西:

awk '{a[NR]=$0} END{bos=1; tos=NR; while (bos < tos) {print a[bos] " -> " a[tos]; delete a[tos--]; delete a[bos++] } }'  file
Red -> Violet
Orange -> Blue
Yellow -> Green

我的脚本和你的不同之处在于,你的脚本会保持“a”不变,但是当我的脚本完成后,如果“a”中最初有偶数个元素,那么它将为空,但如果有奇数,那么初始中间元素将是“a”中剩下的所有元素。例如:

$ cat file                                                                    
Red
Orange
Yellow
Purple
Green
Blue
Violet

$ awk '{a[NR]=$0} END{bos=1; tos=NR; while (bos < tos) {print a[bos] " -> " a[tos]; delete a[tos--]; delete a[bos++] } for (i in a) print a[i] }'  file
Red -> Violet
Orange -> Blue
Yellow -> Green
Purple
于 2012-11-27T22:08:08.600 回答