Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Γεια και χαρά

μήπως γνωρίζει κανείς μια βιβλιοθήκη που να κάνει την παρακάτω δουλειά κάπως πιο αυτόματα και πιο σωστά (pythonic) γιατί μου φαίνεται κακάσχημο αυτό που έγγραψα.

θέλω να φιλτράρω τα αντικείμενα ενός iterator και όταν το 1 έχει 0 δεξιά και αριστερά να γίνεται 0.

Η numpy κάνει κάτι τέτοιο; (δεν ξέρω και πως να το ψάξω στο διαδίκτυο)

 

>>> a=[0,0,0,1,0,1,0,1,1,1,0,1]
>>> a
[0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]
[0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]
>>> b = a[:]
>>> for i in range(1, len(b)):
	if i == len(b) - 1:
		break
	if b[i] == 1 and b[i - 1] == 0 and b[i + 1] == 0:
		a[i] = 0

		
>>> a
[0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1]
>>> b
[0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]
>>> 

 

Δημοσ. (επεξεργασμένο)
a[0:1] + [int(any([a[i - 1], a[i + 1]])) * a[i] for i in range(1, len(a) - 1)] + a[-1:]

 

Και δεν φιλτάρεις iterator αλλά iterable. 

Ο iterator δεν φιλτράρεται. 

Και δεν φιλτράρεις αλλά κάνεις modify. Εφόσον έχουν το ίδιο μήκος οι λίστες, δεν είναι filtering. 

Επεξ/σία από Heyho
Δημοσ. (επεξεργασμένο)
a = [0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]

print 'Before: ', a
for indx, val in enumerate(a):
    if val: # Check for 1
        try:
            if (a[indx - 1] == 0) and a[indx + 1] == 0:
                a[indx] = 0
        except IndexError: # Avoid out of index
            pass
print 'After: ', a

Μπορείς να γράψεις πολύπλοκα και απλά. Σε κάτι απλό σε σύνταξη μπορείς να κάνεις κάτι σαν το παραπάνω. Αλλά γενικά αυτό που χρειάζεσαι είναι
-Βρες τα index που έχουν 1
-Ελέγχεις πριν και μετά αλλά πρόσεξε μη βγεις έξω από  την λίστα σου
-Επεξεργάζεσαι οτι χρειάζεται.

Επεξ/σία από stefanos90_K
Δημοσ. (επεξεργασμένο)

Αν το μετατρεψεις σε string κανε κατι σαν replace '010' με '000'.

Iσως χρεαστει να κανεις replace μεχρι που να μην αλλαζει 

while(newStr=oldΣτρ.replace('010' , '000'))

Επεξ/σία από albNik
Δημοσ.
2 ώρες πριν, DIMITRISG είπε

πιο αυτόματα και πιο σωστά (pythonic) γιατί μου φαίνεται κακάσχημο αυτό που έγγραψα.

 

 

34 λεπτά πριν, stefanos90_K είπε
a = [0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]

print 'Before: ', a
for indx, val in enumerate(a):
    if val: # Check for 1
        try:
            if (a[indx - 1] == 0) and a[indx + 1] == 0:
                a[indx] = 0
        except IndexError: # Avoid out of index
            pass
print 'After: ', a

Μπορείς να γράψεις πολύπλοκα και απλά. Σε κάτι απλό σε σύνταξη μπορείς να κάνεις κάτι σαν το παραπάνω. Αλλά γενικά αυτό που χρειάζεσαι είναι
-Βρες τα index που έχουν 1
-Ελέγχεις πριν και μετά αλλά πρόσεξε μη βγεις έξω από  την λίστα σου
-Επεξεργάζεσαι οτι χρειάζεται.

 

7 λεπτά πριν, albNik είπε

Αν το μετατρεψεις σε string κανε κατι σαν replace '010' με '000'.

Iσως χρεαστει να κανεις replace μεχρι που να μην αλλαζει 

while(newStr=oldΣτρ.replace('010' , '000'))

LOL!!!!

Δεν θέλω να φανταστώ τι θα έβλεπαν τα ματάκια μου εάν δεν έγραφε "πιο αυτόματα και πιο σωστά" ο ΟΡ!!!

36 λεπτά πριν, stefanos90_K είπε

-Ελέγχεις πριν και μετά αλλά πρόσεξε μη βγεις έξω από  την λίστα σου

Εάν κάνεις loop πάνω σε λίστα και καταφέρεις να βγεις εκτός λίστας, σταμάτα να γράφεις σε Python. Έλεος δηλαδή! 

Υ.Γ. Python 2.X το 2019; 

 

Δημοσ.
6 λεπτά πριν, Heyho είπε

LOL!!!!

Δεν θέλω να φανταστώ τι θα έβλεπαν τα ματάκια μου εάν δεν έγραφε "πιο αυτόματα και πιο σωστά" ο ΟΡ!!!

 

Αυτο που ειπα ειναι η ιδεα του replace σε σχεση με το iteration ελεγχοντας τους δεικτες a, i-1, , i+1 κλπ. Θα μπορουσε να το υποστηρίζει και ο πινακας (δεν ξερω python) κατι τετοιο array.replace([1,2,3], [4,5,6])

Δημοσ. (επεξεργασμένο)
1 λεπτό πριν, albNik είπε

Αυτο που ειπα ειναι η ιδεα του replace σε σχεση με το iteration ελεγχοντας τους δεικτες a, i-1, , i+1 κλπ. Θα μπορουσε να το υποστηρίζει και ο πινακας (δεν ξερω python) κατι τετοιο array.replace([1,2,3], [4,5,6])

Εάν δεν ξέρεις Python , τότε γιατί απαντάς; 

Χώρια από το εάν ξέρεις ή όχι, το int σε str και μετά πάλι σε int για να κάνεις replace/modify, είναι όχι απλά λάθος... είναι τρελό μαργαριτάρι. Για να το προτείνεις αυτό, δεν πρέπει να ξέρεις γενικά και όχι μόνο Python. 

Επεξ/σία από Heyho
Δημοσ.
48 λεπτά πριν, Heyho είπε

Εάν δεν ξέρεις Python , τότε γιατί απαντάς; 

Χώρια από το εάν ξέρεις ή όχι, το int σε str και μετά πάλι σε int για να κάνεις replace/modify, είναι όχι απλά λάθος... είναι τρελό μαργαριτάρι. Για να το προτείνεις αυτό, δεν πρέπει να ξέρεις γενικά και όχι μόνο Python. 

καλως τον κυριο clean code και best practice

Δημοσ.
1 ώρα πριν, Heyho είπε

Εάν δεν ξέρεις Python , τότε γιατί απαντάς; 

Χώρια από το εάν ξέρεις ή όχι, το int σε str και μετά πάλι σε int για να κάνεις replace/modify, είναι όχι απλά λάθος... είναι τρελό μαργαριτάρι. Για να το προτείνεις αυτό, δεν πρέπει να ξέρεις γενικά και όχι μόνο Python. 

Τα 0, 1 θα μπορουσαν να ειναι οτιδήποτε. int , bool , string , char...εσυ κόλλησες στη μετατροπή.

Δημοσ.

Μια λύση με numpy (χωρίς loop)

1. Το πρώτο και το τελευταίο στοιχείο του πίνακα δεν μπορούν να αλλάξουν για αυτό και με ασφάλεια μπορούμε να τα αφαιρέσουμε.

import numpy as np

a = np.array([0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1])
b = a[1:-1].copy()
b
# array([0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0])

2. Για να αποφύγουμε να κάνουμε loop, μπορούμε να χρησιμοποιήσουμε την np.roll η οποία μας δίνει ένα νέο πίνακα με μετατοπισμένα indices. Συνδυάζοντας την με την stack παίρνουμε ένα 3xN πίνακα οι στήλες του οποίου είναι το slice a[i-1:i+1]:

c = np.stack(
    (
        np.roll(b, 1), 
        b, 
        np.roll(b, -1)
    ), 
    axis=0
)
c
# array([[0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1],
#        [0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0],
#        [0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0]])

3. To μόνο που μένει να κάνουμε τώρα είναι να βρούμε τα indices από τις στήλες που έχουν την τιμή [0, 1, 0]:

np.all((c.T == (0, 1, 0)).T, axis=0)
# array([False, False,  True, False,  True, False, False, False, False, False, True, False])

4. Στο βήμα 1 αφαιρέσαμε το 1ο και το τελευταίο στοιχείο του πίνακα. Ας τα προσθέσουμε:

indices = np.concatenate(
    (
        np.array([False]),
        np.all((c.T == (0, 1, 0)).T, axis=0),
        np.array([False]),
    ),
    axis=0,
)
indices
# array([False, False, False,  True, False,  True, False, False, False, False, False,  True, False, False])

5. Tέλος ας αντικαταστήσουμε τις τιμές:

final = a.copy()
final[indices] = 0
final
# array([0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1])

Τα copy() δεν χρειάζονται αλλά αν δεν τα βάλουμε τα assignments θα γίνουν inplace και δεν θα μπορούμε να ελέγξουμε τις τιμές των ενδιάμεσων πινάκων στο τέλος.

 

Δημοσ. (επεξεργασμένο)

  Καλησπέρα. Διαβάζοντας το νήμα και με αφορμή το ζητούμενο του θέματος έγραψα μια μίκρη εκδοχή, στη C όμως.
Ίσως νά χει και λάθη, οπότε πείτε το αν δείτε τίποτα. Ο κώδικας και ένα screenshot απ' το πρόγραμμα είναι:

/* Θέλουμε όπου υπάρχει 1 μέσα στον πίνακα και έχει δεξια
   και αριστερά του 0, τότε το 1 να γίνεται κι' αυτό 0. */

#include <stdio.h>

/* Ο πίνακας μας με τα 0 και τα 1 */ 
int arr[] = { 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1 };

/* Με αυτή τη συνάρτηση εκτυπώνουμε τις τιμές του πίνακα */
void print_arr(void);

int main(void)
{
    int i;

    print_arr();   

    /* Εδώ κοιτάμε ο βρόχος να μη πιάνει τα άκρα και να εξετάζει κάθε τιμή άν είναι 1, και κάθε
       προηγούμενη και επόμενη αν είναι 0. Τότε τα 1 γίνονται 0. */         
    for(i = 0; i < 12; i++) {
        if((i > 0) && (i < 11) && i >(arr[i] == 1) && (arr[i-1] == 0) && (arr[i+1] == 0)) { 
            arr[i] = 0;
        }
    }

    print_arr();  
    return 0;
}

void print_arr(void)
{
    int i; 

    for(i = 0; i < 12; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
    

spacer.png

Επεξ/σία από cvb~
Δημοσ.

Και λίγο πιο concisely μπορεί να γίνει έτσι:

import numpy as np

a = np.array([0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1])
c = np.stack((np.roll(a, 1), a, np.roll(a, -1)), axis=0)
indices = np.pad(
    array=np.all((c.T == (0, 1, 0)).T, axis=0)[1:-1],
    pad_width=1,
    mode="constant",
    constant_values=False,
)
a[indices] = 0

 

Δημοσ. (επεξεργασμένο)

Εάν το πρόβλημα είναι η λέξη "for" (γιατί και το "all" με επανάληψη γίνεται), τότε μπορεί κανείς να το κάνει κάπως έτσι: 
 

def filter_my_list(my_list):
    return lambda x: int(any([my_list[x - 1], my_list[x + 1]]) * my_list[x])

a = [0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]
b = a[0:1] + list(map(filter_my_list(a), range(1, len(a) - 1))) + a[-1:]

 

Επεξ/σία από Heyho
Δημοσ. (επεξεργασμένο)
26 minutes ago, Heyho said:

Εάν το πρόβλημα είναι η λέξη "for"

Το «πρόβλημα» προφανώς δεν είναι το keyword "for" αλλά το performance. Από κάποιο Ν και πάνω η python γίνεται τάξεις μεγέθους πιο αργή σε σχέση με τα vectorized operations του numpy. Για πολύ μικρά N δεν αποκλείεται η Python να είναι και πιο γρήγορη γιατί δεν χρειάζεται type conversions.
https://hackernoon.com/speeding-up-your-code-2-vectorizing-the-loops-with-numpy-e380e939bed3

https://realpython.com/numpy-array-programming/

Επίσης το np.all() δεν είναι το ίδιο με το all()

https://stackoverflow.com/a/43382396/592289

Επεξ/σία από pmav99
Δημοσ. (επεξεργασμένο)
27 λεπτά πριν, pmav99 είπε

Το «πρόβλημα» προφανώς δεν είναι το keyword "for" αλλά το performance. Από κάποιο Ν και πάνω η python γίνεται τάξεις μεγέθους πιο αργή σε σχέση με τα vectorized operations του numpy. Για πολύ μικρά N δεν αποκλείεται η Python να είναι και πιο γρήγορη γιατί δεν χρειάζεται type conversions.
https://hackernoon.com/speeding-up-your-code-2-vectorizing-the-loops-with-numpy-e380e939bed3

https://realpython.com/numpy-array-programming/

Επίσης το np.all() δεν είναι το ίδιο με το all()

https://stackoverflow.com/a/43382396/592289

Το performance δεν το σκέφτηκα, εστίασα στο paradigm και τον αλγόριθμο. Συμφωνώ για το performance των vectorized operations. 

Τέλος, ίδια δεν είναι τα all, αλλά έχουν επανάληψη. Υλοποιούνται με επανάληψη. 

28 λεπτά πριν, tsofras είπε

@Heyho πολύ χολή ρε φίλε έβγαλες σε κόσμο που προσπάθησε απλά να βοηθήσει. Χίλιες φορές να συνεργάζομαι με άτομα σαν τα παιδιά που υποβιβαζεις παρά με άτομα σαν και εσένα.

Εξήγησέ μου με ποιον τρόπο κάποιος βοηθάει τον ΟΡ όταν ο ίδιος παραδέχεται ότι δεν γνωρίζει αυτό για το οποίο ρωτάει ο ΟΡ. 

Πάτε καλά ορισμένοι; Μπαίνει κάποιος και ρωτάει κάτι πολύ συγκεκριμένο: Πώς μπορώ να κάνω κάτι ΣΤΗΝ ΓΛΩΣΣΑ PYTHON.

και το γράφει δύο φορές ότι είναι για Python. Μία στον τίτλο και μία στο κείμενο.

Πετάγεται ένας και απαντάει, λέγοντας μετά ότι δεν γνωρίζει Python, και πάτε και τον υπερασπίζεστε ότι και καλά «βοηθάει». Πώς; Πώς βοηθάει ΑΦΟΥ ΔΕΝ ΓΝΩΡΙΖΕΙ ΓΙΑ ΝΑ ΑΠΑΝΤΗΣΕΙ; Δεν το λέω εγώ ότι δεν γνωρίζει. ΤΟ ΕΙΠΕ Ο ΙΔΙΟΣ!

Πάτε καλά;

Επεξ/σία από Heyho

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...