How do I combine elements in a list, e.g.
List(('h', 1), ('i', 1), ('h', 1), ('i', 1), ('l', 2))
such that I get the following result:
List(('h', 2), ('i', 2), ('l', 2))
Basically, I want to sum the numbers associated with each letter, and the letter should appear in the list only once.
val myList = List(('h', 1), ('i', 3), ('h', 5), ('i', 7), ('l', 2))
myList.groupBy(_._1).mapValues(_.foldLeft(0)(_ + _._2)).toList
res0: List[(Char, Int)] = List((h,6), (i,10), (l,2))
val df = List(('h', 1), ('i', 1), ('h', 1), ('i', 1), ('l', 2))
val c = df.groupBy(_._1).mapValues(_.map(_._2).sum).toList
List((h,2), (i,2), (l,2))
you can do:
val h = List(('h', 3), ('i', 1), ('h', 1), ('i', 1), ('l', 2))
h.groupBy(_._1).map(f => (f._1, f._2.map(_._2).sum)).toList
Related
I want to check if a list is a subset of another, based on the first element in its tuple.
subset(List(('a', 1), ('b', 2), ('c', 3)), List(('a', 4), ('b', 5)) // True
subset(List(('a', 1), ('b', 2), ('c', 3)), List(('a', 4), ('b', 5), ('f', 6)) // False
The size of the lists does not have to be the same. I've tried something like this, but with no luck
x.forall((char: Char, num: Int) => {y.contains((_,num))})
You can map in the input lists to retain only the first element, then use some set functionality to check equality:
def subset(a: List[(Char, Int)], b: List[(Char, Int)]): Boolean = {
val a_ = a.map(_._1).toSet
val b_ = b.map(_._1).toSet
b_.subsetOf(a_)
}
Update: Simplified based on suggestion from Luis
I am new to both Python and NetworkX. I have a square, regular graph G with NxN nodes (a lattice). Such nodes are labelled by means of a dict (see code below). Now I want the edgelist to return the start and endpoint of each edge not by referring to the node coordinates but to the label the node has been given.
Example:
N = 3
G=nx.grid_2d_graph(N,N)
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
#This gives nodes an attribute ID that is identical to their labels
for (i,j) in labels:
G.node[(i,j)] ['ID']= labels[(i,j)]
edgelist=G.edges() #This gives the list of all edges in the format (Start XY, End XY)
If I run it with N=3 I get:
In [14]: labels
Out[14]: {(0, 0): 6, (0, 1): 3, (0, 2): 0, (1, 0): 7, (1, 1): 4, (1, 2): 1, (2, 0): 8, (2, 1): 5, (2, 2): 2}
This scheme labels the upper left node as 0, with node (N-1)th being placed in the lower right corner. And this is what I want. Now the problem with edgelist:
In [15]: edgelist
Out [15]: [((0, 1), (0, 0)), ((0, 1), (1, 1)), ((0, 1), (0, 2)), ((1, 2), (1, 1)), ((1, 2), (0, 2)), ((1, 2), (2, 2)), ((0, 0), (1, 0)), ((2, 1), (2, 0)), ((2, 1), (1, 1)), ((2, 1), (2, 2)), ((1, 1), (1, 0)), ((2, 0), (1, 0))]
I tried to solve the problem with these lines (inspiration from here: Replace items in a list using a dictionary):
allKeys = {}
for subdict in (labels):
allKeys.update(subdict)
new_edgelist = [allKeys[edge] for edge in edgelist]
but I get this wonderful thing which enlightens my monday:
TypeError: cannot convert dictionary update sequence element #0 to a sequence
To sum up, I want to be able to replace the elements of the edgelist list with the values of the labels dictionary so that, say, the edge from ((2,0),(1,0)) (which correspond to nodes 8 and 7) is returned (8,7). Endless thanks!
I believe what you are looking for is simply nx.relabel_nodes(G,labels,False) here is the documentation
Here is the output when I printed the nodes of G before and after calling the relabel nodes function.
# Before relabel_nodes
[(0, 1), (1, 0), (0, 0), (1, 1)]
# After relabel_nodes
[0, 1, 2, 3]
After doing this, the edge labels automatically becomes what you expect.
# Edges before relabelling nodes
[((0, 1), (0, 0)), ((0, 1), (1, 1)), ((1, 0), (0, 0)), ((1, 0), (1, 1))]
# Edges after relabelling nodes
[(0, 1), (0, 2), (1, 3), (2, 3)]
Also, I have replied to this question in the chat that you created but it seems you were not notified.
I have a set of x and y coordinates as follows:
x = (1,1,2,2,3,4)
y= (0,1,2,3,4,5)
What is the best way of going about transforming this list into a multiline string format, e.g:
x_y = [((1,0)(1,1)),((1,1)(2,2)),((2,2)(2,3)),((2,3)(3,4)),((3,4)(4,5))]
You can pair up the elements of x and y with zip():
>>> x = (1,1,2,2,3,4)
>>> y = (0,1,2,3,4,5)
>>> xy = zip(x, y)
>>> xy
[(1, 0), (1, 1), (2, 2), (2, 3), (3, 4), (4, 5)]
Then you can rearrange this into the kind of list in your example with a list comprehension:
>>> x_y = [(xy[i], xy[i+1]) for i in xrange(len(xy)-1)]
>>> x_y
[((1, 0), (1, 1)), ((1, 1), (2, 2)), ((2, 2), (2, 3)), ((2, 3), (3, 4)), ((3, 4), (4, 5))]
If you don't care about efficiency, the second part could also be written as:
>>> x_y = zip(xy, xy[1:])
How do I perform an operation that checks the IDs and removes the different elements of the first list and adds the different elements of the second list?
The letters are a Entity Id. The numbers are a object reference in memory.
List 1: A:1, B:2, C:3, D:4, E:5
List 2: B:6, C:7, E:8, F:9
RemovedElements: A:1, D:4
InvalidElements: B:6, C:7, E:8
ResultList: B:2, C:3, E:5, F:9
Does anyone know if there is any function that performs this operation?
scala> val l1 = Seq(('A', 1), ('B', 2), ('C', 3), ('D', 4), ('E', 5))
l1: Seq[(Char, Int)] = List((A,1), (B,2), (C,3), (D,4), (E,5))
scala> val l2 = Seq(('B', 6), ('C', 7), ('E', 8), ('F', 9))
l2: Seq[(Char, Int)] = List((B,6), (C,7), (E,8), (F,9))
scala> l2 map { e =>
| l1.find(_._1 == e._1).getOrElse(e)
| }
res51: Seq[(Char, Int)] = List((B,2), (C,3), (E,5), (F,9))
I have a list of (label, count) tuples like this:
[('grape', 100), ('grape', 3), ('apple', 15), ('apple', 10), ('apple', 4), ('banana', 3)]
From that I want to sum all values with the same label (same labels always adjacent) and return a list in the same label order:
[('grape', 103), ('apple', 29), ('banana', 3)]
I know I could solve it with something like:
def group(l):
result = []
if l:
this_label = l[0][0]
this_count = 0
for label, count in l:
if label != this_label:
result.append((this_label, this_count))
this_label = label
this_count = 0
this_count += count
result.append((this_label, this_count))
return result
But is there a more Pythonic / elegant / efficient way to do this?
itertools.groupby can do what you want:
import itertools
import operator
L = [('grape', 100), ('grape', 3), ('apple', 15), ('apple', 10),
('apple', 4), ('banana', 3)]
def accumulate(l):
it = itertools.groupby(l, operator.itemgetter(0))
for key, subiter in it:
yield key, sum(item[1] for item in subiter)
print(list(accumulate(L)))
# [('grape', 103), ('apple', 29), ('banana', 3)]
using itertools and list comprehensions
import itertools
[(key, sum(num for _, num in value))
for key, value in itertools.groupby(l, lambda x: x[0])]
Edit: as gnibbler pointed out: if l isn't already sorted replace it with sorted(l).
import collections
d=collections.defaultdict(int)
a=[]
alist=[('grape', 100), ('banana', 3), ('apple', 10), ('apple', 4), ('grape', 3), ('apple', 15)]
for fruit,number in alist:
if not fruit in a: a.append(fruit)
d[fruit]+=number
for f in a:
print (f,d[f])
output
$ ./python.py
('grape', 103)
('banana', 3)
('apple', 29)
>>> from itertools import groupby
>>> from operator import itemgetter
>>> L=[('grape', 100), ('grape', 3), ('apple', 15), ('apple', 10), ('apple', 4), ('banana', 3)]
>>> [(x,sum(map(itemgetter(1),y))) for x,y in groupby(L, itemgetter(0))]
[('grape', 103), ('apple', 29), ('banana', 3)]
my version without itertools
[(k, sum([y for (x,y) in l if x == k])) for k in dict(l).keys()]
Method
def group_by(my_list):
result = {}
for k, v in my_list:
result[k] = v if k not in result else result[k] + v
return result
Usage
my_list = [
('grape', 100), ('grape', 3), ('apple', 15),
('apple', 10), ('apple', 4), ('banana', 3)
]
group_by(my_list)
# Output: {'grape': 103, 'apple': 29, 'banana': 3}
You Convert to List of tuples like list(group_by(my_list).items()).
Or a simpler more readable answer ( without itertools ):
pairs = [('foo',1),('bar',2),('foo',2),('bar',3)]
def sum_pairs(pairs):
sums = {}
for pair in pairs:
sums.setdefault(pair[0], 0)
sums[pair[0]] += pair[1]
return sums.items()
print sum_pairs(pairs)
Simpler answer without any third-party libraries:
dct={}
for key,value in alist:
if key not in dct:
dct[key]=value
else:
dct[key]+=value