5

I need code that loops between each pair of features in sequence (feature 1 with feature 2, feature 2 with feature 3...) but using only a for, I searched the forum and found similar code but with two "for" and one "if", having to go through the entire list again every time the loop happens, would there be a way for me to do this with just one for? I tried using something like "next feature" but it failed.

The original code:

iter1 = layer.getFeatures()
for feature1 in iter1:
    p1 = feature1.geometry().asPoint()
    # loop all points again:
    iter2 = layer.getFeatures()
    for feature2 in iter2:
        # following line creates lines from one feature to previous feature:
        if feature2.id() == feature1.id() + 1:
            # create new line feature:
            p2 = feature2.geometry().asPoint()
            l = QgsGeometry.fromPolylineXY([p1,p2])
            linha = QgsFeature()
            linha.setGeometry(l)
            linha.setAttributes([l.length()])
            pr.addFeature(linha)

My code attempt:

features = layer.getFeatures()
for index, actualFeature in enumerate(features):
    p1 = actualFeature.geometry().asPoint()
    # loop all points again:
    nextFeature = features.index()+1
    
    # create new line feature:
    p2 = nextFeature.geometry().asPoint()
    l = QgsGeometry.fromPolylineXY([p1,p2])
    linha = QgsFeature()
    linha.setGeometry(l)
    linha.setAttributes([l.length()])
    pr.addFeature(linha)


vl.updateFields()
QgsProject.instance().addMapLayer(vl)

But one of the problems is that QgsFeatureIterator object has no attribute 'index', and I think I didn't use PyQGIS correctly. I'm still new to this language, could anyone correct the code to my idea?

4
  • 3
    I doubt you need an exotic looping construct. Just maintain a "previous" variable, initialized to None , then handle initialization on the first iteration, compare actual to previous and put a previous = actual at the end of the loop. Try it on something simple first, like a range(10) then step up to features.
    – Vince
    Commented Dec 12, 2023 at 3:59
  • I think I managed to solve the problem, I put it in the edit of the question, thanks for the help
    – Mestrexama
    Commented Dec 16, 2023 at 5:09
  • Please, put your solution as a valid answer instead of the edit.
    – Taras
    Commented Dec 16, 2023 at 7:35
  • Sorry, I just added it as a valid answer
    – Mestrexama
    Commented Dec 16, 2023 at 12:50

3 Answers 3

7

You can use zip and indexing:

layer = iface.activeLayer()
featurelist = [f for f in layer.getFeatures()] #List all features

for featurepair in zip(featurelist[::2], featurelist[1::2]):
    f1, f2 = featurepair
    print(f1["id"], f2["id"])

enter image description here

0
5

In most latest QGIS versions like QGIS 3.34.1 Prizren​, it should come with the pairwise() function from the itertool module. Since Python 3.10.

# imports
from itertools import pairwise
from qgis.core import QgsProject

# getting a layer by its name
layer = QgsProject.instance().mapLayersByName("YOUR_LAYER_NAME")[0]
# a list of all features in the layer
features = [feat for feat in layer.getFeatures()]

# looping over pairs of features
for pair in pairwise(features):
    feat1, feat2 = pair[0], pair[1]
    print(feat1["id"], feat2["id"])

For earlier version of QGIS, one can use the following approach:

# imports
from qgis.core import QgsProject

# getting a layer by its name
layer = QgsProject.instance().mapLayersByName("YOUR_LAYER_NAME")[0]
# a list of all features in the layer
features = [feat for feat in layer.getFeatures()]

# looping over pairs of features
for i in range(len(features) - 1):
    feat1, feat2 = features[i], features[i + 1]
    print(feat1["id"], feat2["id"])

Keep in mind, that features in the may not come sorted, therefore one may find this thread useful: Sorting features by attribute using PyQGIS


References:

1
  • 1
    I added a solution I found as an answer, you are welcome to see
    – Mestrexama
    Commented Dec 16, 2023 at 12:49
2

I solved the problem, here's the new code:

from qgis.core import QgsProject, QgsGeometry

layer = QgsProject.instance().mapLayersByName("YOUR_LAYER_NAME")[0]
features = [f for f in layer.getFeatures()]

for index, actualFeature in enumerate(features[:-1]):
    p1 = actualFeature.geometry().asPoint()
    # loop all points again:
    nextFeature = features[index+1]
    # create new line feature:
    p2 = nextFeature.geometry().asPoint()
    l = QgsGeometry.fromPolylineXY([p1,p2])
    linha = QgsFeature()
    linha.setGeometry(l)
    linha.setAttributes([l.length()])
    pr.addFeature(linha)


vl.updateFields()
QgsProject.instance().addMapLayer(vl)
1
  • So happy to hear, that you found a solution to your own problem! It is a pleasure to see how people learn and educate themself :)
    – Taras
    Commented Dec 16, 2023 at 13:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.