user690462
user690462

Reputation: 129

How to combine two list that contain intervals

I have list 1 and 2 and I would like to get list 3. If anyone can suggest python or awk script, that would be great.

List 1
A   100-160
B   200-500
C   800-1500
D   1600-2000
E   2500-3000

List 2
150
600
900
1700
2400


List 3
A   100-160        150
B   200-500 
C   800-1500    900
D   1600-2000   1700
E   2500-3000   

Upvotes: 2

Views: 685

Answers (7)

Vijay
Vijay

Reputation: 67211

Do it simply on the command line.So far this is the only awk solution among all:

 paste list1 list2|awk '{split($2,a,"-");
                           if($3>a[1] && $3<a[2])
                           {h=$3}
                           else
                           {h=""};
                           print $1,$2,h}'

A 100-160 150
B 200-500
C 800-1500 900
D 1600-2000 1700
E 2500-3000

Upvotes: 1

tgray
tgray

Reputation: 8966

Here's my take. I just made up the parsing and printing bit since you didn't specify.

list_1 = ['A\t100-160', 'B\t200-500', 'C\t800-1500', 'D\t1600-2000', 'E\t2500-3000']
list_2 = [150, 600, 900, 1700, 2400]

for range in list_1:
    # parse the input (this may be different, but you didn't specify)
    lower_bound, upper_bound = range.split('\t')[1].split('-')  # this is a bit fragile
    lower_bound = int(lower_bound)
    upper_bound = int(upper_bound)

    # make sure lower_bound is less than upper_bound
    if upper_bound < lower_bound:
        (lower_bound, upper_bound) = (upper_bound, lower_bound)

    # loop over list 2 and see if any fall into the current range
    items_in_range = [str(number) for number in list_2 if lower_bound <= number < upper_bound]

    # output List 3
    print range + '\t' + ','.join(items_in_range)

Upvotes: 0

Praveen Gollakota
Praveen Gollakota

Reputation: 38930

You can use iterable tools to write this. Not all too readable but this works. Definitely was fun to write!

from itertools import chain

nameranges = ['A', '100-160', 'B', '200-500', 'C', '800-1500', 'D', '1600-2000', 
              'E', '2500-3000']

values = [150, 600, 900, 1700, 2400]
z = zip(nameranges[0::2], ( map(int, x.split("-")) for x in nameranges[1::2]))
f = list(chain(* (map(lambda x, y: (x[0][0], x[1][0], x[1][1], y) 
               if x[1][0]<=y<=x[1][1] else (x[0], x[1][0], x[1][1]), 
               z, values))))
# print f
#['A', 100, 160, 150, 'B', 200, 500, 'C', 800, 1500, 900, 'D', 1600, 2000, 1700, 
# 'E', 2500, 3000]

Upvotes: 0

the Tin Man
the Tin Man

Reputation: 160551

Dunno for sure if Ruby is needed, but here's a quick pass at it:

list1 = %w[ A 100-160 B 200-500 C 800-1500 D 1600-2000 E 2500-3000 ]
list2 = %w[ 150, 600, 900, 1700, 2400 ]

list3 = []

list1.each_slice(2) do |char, range|
  min_range, max_range = range.split('-').map{ |i| i.to_i }
  l2 = list2.shift
  case l2.to_i
  when min_range..max_range
    list3 << [ char, range, l2 ]
  else
    list3 << [ char, range ]
  end
end

require 'pp'
pp list3

>> [["A", "100-160", "150,"],
>>  ["B", "200-500"],
>>  ["C", "800-1500", "900,"],
>>  ["D", "1600-2000", "1700,"],
>>  ["E", "2500-3000"]]

Upvotes: 0

Matt Habel
Matt Habel

Reputation: 1543

You could make a dictionary from list 1 that contains the intervals then loops through it to see if any value in list 2 is inside the range. For example,

list1 = {"A": [100, 160], "B": [200, 500], "C": [800, 1500],
         "D": [1600, 2000], "E": [2500,3000]}

list2 = [150, 600, 900, 1700, 2400]

for key, val in list1.iteritems():
    for num in list2:
        if num in range(val[0], val[1]):
            val.append(num)

for key, val in sorted(list1.iteritems()):
    print key, ":", val

Upvotes: 2

FuzzyWuzzy
FuzzyWuzzy

Reputation: 805

Here is an example. It is expecting two filenames to be passed on the command line.

import sys

if len(sys.argv) != 3:
    print 'parameters: list1 list2'
    sys.exit(1)

list1 = []
for line in file(sys.argv[1]):
    fields = line.split()
    f1 = fields[0]
    f2, f3 = fields[1].split('-')
    list1.append((f1, int(f2), int(f3), [], ))

for line in file(sys.argv[2]):
    value = int(line)
    for name, lb, ub, values in list1:
        if value >= lb and value <= ub:
            values.append(str(value))

for name, lb, ub, values in list1:
    if values: vals = ','.join(values)
    else: vals = ''
    print '%s %d-%d %s' % (name, lb, ub, vals, )

Upvotes: 2

Mu Mind
Mu Mind

Reputation: 11194

You could do something like this in Python:

L1 = [(100, 160), (200, 500), (800, 1500), (1600, 2000), (2500, 3000)]
L2 = [150, 600, 900, 1700, 2400]
L3 = [((a, b), [i for i in L2 if a<=i<b]) for (a, b) in L1]

It's easy to parse the data into that structure if that's what you want (and print it back out), but I'll wait until you explain what format the data comes in and what format you need it in, because I have a feeling there will be a catch to it.

Upvotes: 1

Related Questions