Repository: networkx/networkx

Issue:
nx.DiGraph.to_undirected() not working as expected for bidirectional edges when using as_view = True
Problem: When using `to_undirected()` on a DiGraph the properties are inconsistent, i.e., differ depending on if as_view was set to True or False. More precisely, the reported degree is not as expected when using `as_view = True`. I guess this might also have an effect on other properties that depend on degree.

### Current Behavior

The node degree of the undirected graph returned by `to_undirected()` is different depending on if as_view was set to True or False. If the directed graph had bidirectional edges, the degree is off by approx. a factor of 2 in the graph view. Everything works as expected if as_view is set to false.

### Expected Behavior

`G.to_undirected(as_view = False).degree()` and `G.to_undirected(as_view = True).degree()` should behave the same.

### Steps to Reproduce

```
import networkx as nx
import sys

print(sys.version) # 3.10.8 | packaged by conda-forge | (main, Nov 24 2022, 14:07:00) [MSC v.1916 64 bit (AMD64)]
print(nx.__version__) # 2.8.8

G = nx.DiGraph()
G.add_nodes_from(["v0","v1","v2"])
G.add_edges_from([("v0","v1"),("v1","v0"),("v1","v2")])
print(G.degree()) # Correct [('v0', 2), ('v1', 3), ('v2', 1)]

G_undir_1 = G.to_undirected(as_view = False)
print(G_undir_1.degree()) # Correct [('v0', 1), ('v1', 2), ('v2', 1)]

G_undir_2 = G.to_undirected(as_view = True)
print(G_undir_2.degree()) # Incorrect [('v0', 2), ('v1', 3), ('v2', 1)]
```

### Environment

<!--- Please provide details about your local environment -->

Python version: 3.10.8
NetworkX version: 2.8.8

### Additional context

n/a



Discussion:
@MridulS @paulitapb @rossbar @jarrodmillman you guys should look at this issue

Resolving patch:
diff --git a/networkx/classes/coreviews.py b/networkx/classes/coreviews.py
--- a/networkx/classes/coreviews.py
+++ b/networkx/classes/coreviews.py
@@ -134,7 +134,7 @@ def __init__(self, succ, pred):
         self._pred = pred
 
     def __len__(self):
-        return len(self._succ) + len(self._pred)
+        return len(self._succ.keys() | self._pred.keys())
 
     def __iter__(self):
         return iter(set(self._succ.keys()) | set(self._pred.keys()))


Test patch:
diff --git a/networkx/classes/tests/test_coreviews.py b/networkx/classes/tests/test_coreviews.py
--- a/networkx/classes/tests/test_coreviews.py
+++ b/networkx/classes/tests/test_coreviews.py
@@ -155,7 +155,7 @@ def test_pickle(self):
         assert view.__slots__ == pview.__slots__
 
     def test_len(self):
-        assert len(self.av) == len(self.s) + len(self.p)
+        assert len(self.av) == len(self.s.keys() | self.p.keys()) == 5
 
     def test_iter(self):
         assert set(self.av) == set(self.s) | set(self.p)
@@ -257,7 +257,7 @@ def setup_method(self):
         self.adjview = nx.classes.coreviews.UnionMultiInner(self.s, self.p)
 
     def test_len(self):
-        assert len(self.adjview) == len(self.s) + len(self.p)
+        assert len(self.adjview) == len(self.s.keys() | self.p.keys()) == 4
 
     def test_getitem(self):
         assert self.adjview[1] is not self.s[1]