Verification: a143cc29221c9be0

Php array remove all duplicates

Php array remove all duplicates

C++

#include

using namespace std;

char *removeDuplicate(char str[], int n)

{

   int index = 0;  

   for (int i=0; i

     int j; 

     for (j=0; j

        if (str[i] == str[j])

           break;

     if (j == i)

        str[index++] = str[i];

   }

   return str;

}

int main()

{

   char str[]= "geeksforgeeks";

   int n = sizeof(str) / sizeof(str[0]);

   cout

   return 0;

}

Java

import java.util.*;

class GFG

{

    static String removeDuplicate(char str[], int n)

    {

        int index = 0;

        for (int i = 0; i

        {

            int j;

            for (j = 0; j

            {

                if (str[i] == str[j])

                {

                    break;

                }

            }

            if (j == i)

            {

                str[index++] = str[i];

            }

        }

        return String.valueOf(Arrays.copyOf(str, index));

    }

    public static void main(String[] args)

    {

        char str[] = "geeksforgeeks".toCharArray();

        int n = str.length;

        System.out.println(removeDuplicate(str, n));

    }

}

Python3

def removeDuplicate(str, n):

    index = 0

    for i in range(0, n):

        for j in range(0, i + 1):

            if (str[i] == str[j]):

                break

        if (j == i):

            str[index] = str[i]

            index += 1

    return "".join(str[:index])

str= "geeksforgeeks"

n = len(str)

print(removeDuplicate(list(str), n))

C#

using System;

using System.Collections.Generic;

class GFG

{

static String removeDuplicate(char []str, int n)

{

    int index = 0;

    for (int i = 0; i

    {

        int j;

        for (j = 0; j

        {

            if (str[i] == str[j])

            {

                break;

            }

        }

        if (j == i)

        {

            str[index++] = str[i];

        }

    }

    char [] ans = new char[index];

    Array.Copy(str, ans, index);

    return String.Join("", ans);

}

public static void Main(String[] args)

{

    char []str = "geeksforgeeks".ToCharArray();

    int n = str.Length;

    Console.WriteLine(removeDuplicate(str, n));

}

}

Javascript

function removeDuplicate(str, n)

    {

        var index = 0;

        for (var i = 0; i

        {

            var j;

            for (j = 0; j

            {

                if (str[i] == str[j])

                {

                    break;

                }

            }

            if (j == i)

            {

                str[index++] = str[i];

            }

        }

        return str.join("").slice(str, index);

    }

        var str = "geeksforgeeks".split("");

        var n = str.length;

        document.write(removeDuplicate(str, n));

C++

#include

using namespace std;

char *removeDuplicate(char str[], int n)

{

    setchar>s (str, str+n-1);

    int i = 0;

    for (auto x : s)

       str[i++] = x;

    str[i] = '\0';

    return str;

}

int main()

{

   char str[]= "geeksforgeeks";

   int n = sizeof(str) / sizeof(str[0]);

   cout

   return 0;

}

Java

import java.util.*;

class GFG{

static char []removeDuplicate(char str[], int n)

{

    HashSets = new HashSet(n - 1);

    for(char x : str)

        s.add(x);

    char[] st = new char[s.size()];

    int i = 0;

    for(char x : s)

       st[i++] = x;

    return st;

}

public static void main(String[] args)

{

   char str[]= "geeksforgeeks".toCharArray();

   int n = str.length;

   System.out.print(removeDuplicate(str, n));

}

}

C++

#include

using namespace std;

char *removeDupsSorted(char *str)

{

    int res_ind = 1, ip_ind = 1;

    while (*(str + ip_ind))

    {

        if (*(str + ip_ind) != *(str + ip_ind - 1))

        {

            *(str + res_ind) = *(str + ip_ind);

            res_ind++;

        }

        ip_ind++;

    }

    *(str + res_ind) = '\0';

    return str;

}

char *removeDups(char *str)

{

   int n = strlen(str);

   sort(str, str+n);

   return removeDupsSorted(str);

}

int main()

{

  char str[] = "geeksforgeeks";

  cout

  return 0;

}

C

# include

# include

# include

char *removeDupsSorted(char *str);

void quickSort(char A[], int si, int ei);

char *removeDups(char *str)

{

  int len = strlen(str);

  quickSort(str, 0, len-1);

  return removeDupsSorted(str);

}    

char *removeDupsSorted(char *str)

{

  int res_ind = 1, ip_ind = 1;

  while (*(str + ip_ind))

  {

    if (*(str + ip_ind) != *(str + ip_ind - 1))

    {

      *(str + res_ind) = *(str + ip_ind);

      res_ind++;

    }

    ip_ind++;

  }     

  *(str + res_ind) = '\0';

  return str;

}

int main()

{

  char str[] = "geeksforgeeks";

  printf("%s", removeDups(str));

  getchar();

  return 0;

}

void exchange(char *a, char *b)

{

  char temp;

  temp = *a;

  *a   = *b;

  *b   = temp;

}

int partition(char A[], int si, int ei)

{

  char x = A[ei];

  int i = (si - 1);

  int j;

  for (j = si; j

  {

    if (A[j]

    {

      i++;

      exchange(&A[i], &A[j]);

    }

  }

  exchange (&A[i + 1], &A[ei]);

  return (i + 1);

}

void quickSort(char A[], int si, int ei)

{

  int pi;   

  if (si

  {

    pi = partition(A, si, ei);

    quickSort(A, si, pi - 1);

    quickSort(A, pi + 1, ei);

  }

}

Java

import java.util.Arrays;

public class GFG

{

    static String removeDupsSorted(String str)

    {

        int res_ind = 1, ip_ind = 1;

        char arr[] = str.toCharArray();

        while (ip_ind != arr.length)

        {

            if(arr[ip_ind] != arr[ip_ind-1])

            {

                arr[res_ind] = arr[ip_ind];

                res_ind++;

            }

            ip_ind++;

        }

        str = new String(arr);

        return str.substring(0,res_ind);

    }

    static String removeDups(String str)

    {

       char temp[] = str.toCharArray();

       Arrays.sort(temp);

       str = new String(temp);

       return removeDupsSorted(str);

    }

    public static void main(String[] args)

    {

        String str = "geeksforgeeks";

        System.out.println(removeDups(str));

    }

}

Python

def toMutable(string):

    temp = []

    for x in string:

        temp.append(x)

    return temp

def toString(List):

    return ''.join(List)

def removeDupsSorted(List):

    res_ind = 1

    ip_ind = 1

    while ip_ind != len(List):

        if List[ip_ind] != List[ip_ind-1]:

            List[res_ind] = List[ip_ind]

            res_ind += 1

        ip_ind+=1

    string = toString(List[0:res_ind])

    return string

def removeDups(string):

    List = toMutable(string)

    List.sort()

    return removeDupsSorted(List)

string = "geeksforgeeks"

print removeDups(string)

C#

using System;

class GFG

{

    static String removeDupsSorted(String str)

    {

        int res_ind = 1, ip_ind = 1;

        char []arr = str.ToCharArray();

        while (ip_ind != arr.Length)

        {

            if(arr[ip_ind] != arr[ip_ind-1])

            {

                arr[res_ind] = arr[ip_ind];

                res_ind++;

            }

            ip_ind++;

        }

        str = new String(arr);

        return str.Substring(0,res_ind);

    }

    static String removeDups(String str)

    {

    char []temp = str.ToCharArray();

    Array.Sort(temp);

    str = String.Join("",temp);

    return removeDupsSorted(str);

    }

    public static void Main(String[] args)

    {

        String str = "geeksforgeeks";

        Console.WriteLine(removeDups(str));

    }

}

Javascript

function removeDuplicate(string)

{

   return string.split('')

    .filter(function(item, pos, self)

    {

      return self.indexOf(item) == pos;

    }

   ).join('');

}

var str = "geeksforgeeks";

document.write( " "+removeDuplicate(str));

C++

#include

using namespace std;

# define NO_OF_CHARS 256

# define bool int

char *removeDups(char str[])

{

    bool bin_hash[NO_OF_CHARS] = {0};

    int ip_ind = 0, res_ind = 0;

    char temp;

    while (*(str + ip_ind))

    {

        temp = *(str + ip_ind);

        if (bin_hash[temp] == 0)

        {

            bin_hash[temp] = 1;

            *(str + res_ind) = *(str + ip_ind);

            res_ind++;

        }

        ip_ind++;

    }

    *(str+res_ind) = '\0';

    return str;

}

int main()

{

    char str[] = "geeksforgeeks";

    cout

    return 0;

}

C

# include

# include

# define NO_OF_CHARS 256

# define bool int

char *removeDups(char *str)

{

  bool bin_hash[NO_OF_CHARS] = {0};

  int ip_ind = 0, res_ind = 0;

  char temp;   

  while (*(str + ip_ind))

  {

    temp = *(str + ip_ind);

    if (bin_hash[temp] == 0)

    {

        bin_hash[temp] = 1;

        *(str + res_ind) = *(str + ip_ind);

        res_ind++;

    }

    ip_ind++;

  }     

  *(str+res_ind) = '\0';  

  return str;

}

int main()

{

    char str[] = "geeksforgeeks";

    printf("%s", removeDups(str));

    getchar();

    return 0;

}

Java

import java.util.*;

class RemoveDuplicates

{

    void removeDuplicates(String str)

    {

        LinkedHashSet lhs = new LinkedHashSet();

        for(int i=0;i

            lhs.add(str.charAt(i));

        for(Character ch : lhs)

            System.out.print(ch);

    }

    public static void main(String args[])

    {

        String str = "geeksforgeeks";

        RemoveDuplicates r = new RemoveDuplicates();

        r.removeDuplicates(str);

    }

}

Python

NO_OF_CHARS = 256

def toMutable(string):

    List = []

    for i in string:

        List.append(i)

    return List

def toString(List):

    return ''.join(List)

def removeDups(string):

    bin_hash = [0] * NO_OF_CHARS

    ip_ind = 0

    res_ind = 0

    temp = ''

    mutableString = toMutable(string)

    while ip_ind != len(mutableString):

        temp = mutableString[ip_ind]

        if bin_hash[ord(temp)] == 0:

            bin_hash[ord(temp)] = 1

            mutableString[res_ind] = mutableString[ip_ind]

            res_ind+=1

        ip_ind+=1

    return toString(mutableString[0:res_ind])

string = "geeksforgeeks"

print(removeDups(string))

C#

using System;

using System.Collections.Generic;

class GFG

{

    void removeDuplicates(String str)

    {

        HashSetchar> lhs = new HashSetchar>();

        for(int i = 0; i

            lhs.Add(str[i]);

        foreach(char ch in lhs)

            Console.Write(ch);

    }

    public static void Main(String []args)

    {

        String str = "geeksforgeeks";

        GFG r = new GFG();

        r.removeDuplicates(str);

    }

}

C++

#include

using namespace std;

string unique(string s)

{

    string str;

    int len = s.length();

    for(int i = 0; i

    {

        char c = s[i];

        auto found = str.find(c);

        if (found == std::string::npos)

        {

            str += c;

        }

    }

    return str;

}

int main()

{

    string s = "geeksforgeeks";

    cout

}

Java

import java.util.*;

class IndexOf {

    public static String unique(String s)

    {

        String str = new String();

        int len = s.length();

        for (int i = 0; i

        {

            char c = s.charAt(i);

            if (str.indexOf(c) 0)

            {

                str += c;

            }

        }

        return str;

    }

    public static void main(String[] args)

    {

        String s = "geeksforgeeks";

        System.out.println(unique(s));

    }

}

Python3

def unique(s):

    st = ""

    length = len(s)

    for i in range(length):

        c = s[i]

        if c not in st:

            st += c

    return st

if __name__ == "__main__":

    s = "geeksforgeeks"

    print(unique(s))

C#

using System;

public class IndexOf

{

    public static String unique(String s)

    {

        String str = "";

        int len = s.Length;

        for (int i = 0; i

        {

            char c = s[i];

            if (str.IndexOf(c)

            {

                str += c;

            }

        }

        return str;

    }

    public static void Main(String[] args)

    {

        String s = "geeksforgeeks";

        Console.WriteLine(unique(s));

    }

}

C++

#include

using namespace std;

int removeDups(vectorint>& vect)

{

    int res_ind = 1;

    for (int i = 1; i

        int j;

        for (j = 0; j

            if (vect[i] == vect[j])

                break;

        if (j == i)

            vect[res_ind++] = vect[i];

    }

    vect.erase(vect.begin() + res_ind, vect.end());

}

int main()

{

    vectorint> vect{ 3, 5, 7, 2, 2, 5, 7, 7 };

    removeDups(vect);

    for (int i = 0; i

        cout " ";

    return 0;

}

Java

class GFG {

    static int[] removeDups(int[] vect)

    {

        int res_ind = 1;

        for (int i = 1; i

            int j;

            for (j = 0; j

                if (vect[i] == vect[j])

                    break;

            if (j == i)

                vect[res_ind++] = vect[i];

        }

        int[] new_arr = new int[res_ind];

        for (int i = 0; i

            new_arr[i] = vect[i];

        return new_arr;

    }

    public static void main(String[] args)

    {

        int[] vect = { 3, 5, 7, 2, 2, 5, 7, 7 };

        vect = removeDups(vect);

        for (int i = 0; i

            System.out.print(vect[i] + " ");

        System.out.println();

    }

}

Python3

def removeDups(vect):

    res_ind = 1

    for i in range(1, len(vect)):

        j = 0

        while (j

            if (vect[i] == vect[j]):

                break

            j += 1

        if (j == i):

            vect[res_ind] = vect[i]

            res_ind += 1

    return vect[0:res_ind]

vect = [3, 5, 7, 2, 2, 5, 7, 7]

vect = removeDups(vect)

for i in range(len(vect)):

    print(vect[i], end = " ")

C#

using System;

class GFG {

    static int[] removeDups(int[] vect)

    {

        int res_ind = 1;

        for (int i = 1; i

            int j;

            for (j = 0; j

                if (vect[i] == vect[j])

                    break;

            if (j == i)

                vect[res_ind++] = vect[i];

        }

        int[] new_arr = new int[res_ind];

        for (int i = 0; i

            new_arr[i] = vect[i];

        return new_arr;

    }

    public static void Main(String[] args)

    {

        int[] vect = { 3, 5, 7, 2, 2, 5, 7, 7 };

        vect = removeDups(vect);

        for (int i = 0; i

            Console.Write(vect[i] + " ");

        Console.WriteLine();

    }

}

Javascript

    function removeDups(vect)

    {

        let res_ind = 1;

        for (let i = 1; i

            let j;

            for (j = 0; j

                if (vect[i] == vect[j])

                    break;

            if (j == i)

                vect[res_ind++] = vect[i];

        }

        let new_arr = new Array(res_ind);

        for (let i = 0; i

            new_arr[i] = vect[i];

        return new_arr;

    }

    let vect=[3, 5, 7, 2, 2, 5, 7, 7];

    vect = removeDups(vect);

    for (let i = 0; i

        document.write(vect[i] + " ");

    document.write("
"
);

C++

#include

using namespace std;

int removeDups(vectorint>& vect)

{

    sort(vect.begin(), vect.end());

    vect.erase(unique(vect.begin(), vect.end()),

               vect.end());

}

int main()

{

    vectorint> vect{ 3, 5, 7, 2, 2, 5, 7, 7 };

    removeDups(vect);

    for (int i = 0; i

        cout " ";

    return 0;

}

Java

import java.util.*;

class GFG {

    static int[] removeDups(int[] vect)

    {

        Arrays.sort(vect);

        int first = 1;

        for (int i = 1; i

            if (vect[i] != vect[i - 1])

                vect[first++] = vect[i];

        for (int i = first; i

            vect[i] = Integer.MAX_VALUE;

        return vect;

    }

    public static void main(String[] args)

    {

        int[] vect = { 3, 5, 7, 2, 2, 5, 7, 7 };

        vect = removeDups(vect);

        for (int i = 0; i

            if (vect[i] == Integer.MAX_VALUE)

                break;

            System.out.print(vect[i] + " ");

        }

    }

}

Python3

import sys

def removeDups(vect):

    vect.sort()

    first = 1

    for i in range(1, len(vect)):

        if (vect[i] != vect[i - 1]):

            vect[first] = vect[i]

            first += 1

    for  i in range(first, len(vect)):

        vect[i] = sys.maxsize

    return vect

vect = [ 3, 5, 7, 2, 2, 5, 7, 7 ]

vect = removeDups(vect)

for i in range(len(vect)):

    if (vect[i] == sys.maxsize):

        break

    print(vect[i], end = " ")

C#

using System;

class GFG

{

    static int[] removeDups(int[] vect)

    {

        Array.Sort(vect);

        int first = 1;

        for (int i = 1; i

            if (vect[i] != vect[i - 1])

                vect[first++] = vect[i];

        for (int i = first; i

            vect[i] = int.MaxValue;

        return vect;

    }

    public static void Main(params string[] args)

    {

        int[] vect = { 3, 5, 7, 2, 2, 5, 7, 7 };

        vect = removeDups(vect);

        for (int i = 0; i

        {

            if (vect[i] == int.MaxValue)

                break;

            Console.Write(vect[i] + " ");

        }

    }

}

Javascript

function removeDups(vect) {

    vect.sort((a, b) => a - b)

    let first = 1;

    for (let i = 1; i

        if (vect[i] != vect[i - 1])

            vect[first++] = vect[i];

    }

    for (let i = first; i

        vect[i] = Number.MAX_SAFE_INTEGER;

    return vect;

}

    let vect = [ 3, 5, 7, 2, 2, 5, 7, 7 ];

    removeDups(vect);

    for (let i = 0; i

        if (vect[i] == Number.MAX_SAFE_INTEGER)

            break;

        document.write(vect[i] + " ");

    }

C++

#include

using namespace std;

int removeDups(vectorint>& vect)

{

    unordered_setint> s(vect.begin(), vect.end());

    vect.assign(s.begin(), s.end());

}

int main()

{

    vectorint> vect{ 3, 5, 7, 2, 2, 5, 7, 7 };

    removeDups(vect);

    for (int i = 0; i

        cout " ";

    return 0;

}

Java

import java.util.*;

class GFG {

    static void removeDups(Vector vect)

    {

        Set set = new HashSet(vect);

        vect.clear();

        vect.addAll(set);

    }

    public static void main(String[] args)

    {

        Integer arr[] = { 3, 5, 7, 2, 2, 5, 7, 7 };

        Vector vect

            = new Vector(

                Arrays.asList(arr));

        removeDups(vect);

        for (int i = 0; i

            System.out.print(vect.get(i) + " ");

        }

    }

}

Python3

def removeDups():

    global vect

    s = set(vect)

    vect = s

vect = [3, 5, 7, 2, 2, 5, 7, 7]

removeDups()

for i in vect:

    print(i, end = " ")

C#

using System;

using System.Collections.Generic;

using System.Linq;

class GFG {

    static Listint> removeDups(Listint> vect)

    {

        HashSetint> set = new HashSetint>(vect);

        vect.Clear();

        vect = set.ToList();

        return vect;

    }

    public static void Main(String[] args)

    {

        int[] arr = { 3, 5, 7, 2, 2, 5, 7, 7 };

        Listint> vect = new Listint>(arr);

        vect = removeDups(vect);

        for (int i = 0; i

            Console.Write(vect[i] + " ");

        }

    }

}

Javascript

function removeDups(vect)

{

        letset = new Set(vect);

        vect=[];

        vect=Array.from(letset);

        return vect;

}

let vect=[3, 5, 7, 2, 2, 5, 7, 7 ];

vect=removeDups(vect);

for (let i = 0; i

    document.write(vect[i] + " ");

}

C++

#include

using namespace std;

int removeDups(vectorint>& vect)

{

    long long int prod = vect[0];

    int res_ind = 1;

    for (int i = 1; i

        if (prod % vect[i] != 0) {

            vect[res_ind++] = vect[i];

            prod *= vect[i];

        }

    }

    vect.erase(vect.begin() + res_ind, vect.end());

}

int main()

{

    vectorint> vect{ 3, 5, 7, 2, 2, 5, 7, 7 };

    removeDups(vect);

    for (int i = 0; i

        cout " ";

    return 0;

}

Java

import java.util.*;

class GFG {

    static int[] removeDups(int[] vect)

    {

        int prod = vect[0];

        int res_ind = 1;

        for (int i = 1; i

            if (prod % vect[i] != 0) {

                vect[res_ind++] = vect[i];

                prod *= vect[i];

            }

        }

        return Arrays.copyOf(vect, res_ind);

    }

    public static void main(String[] args)

    {

        int[] vect = { 3, 5, 7, 2, 2, 5, 7, 7 };

        vect = removeDups(vect);

        for (int i = 0; i

            System.out.print(vect[i] + " ");

    }

}

Python3

def removeDups(vect):

    prod = vect[0]

    res_ind = 1

    i = 1

    while (i len(vect)):

        if (prod % vect[i] != 0):

            vect[res_ind] = vect[i]

            res_ind += 1

            prod *= vect[i]

        vect = vect[:res_ind + 2]

        i += 1

    return vect

vect = [3, 5, 7, 2, 2, 5, 7, 7]

vect = removeDups(vect)

for i in range(len(vect)):

    print(vect[i], end =" ")

C#

using System;

class GFG {

    static int[] removeDups(int[] vect)

    {

        int prod = vect[0];

        int res_ind = 1;

        for (int i = 1; i

            if (prod % vect[i] != 0) {

                vect[res_ind++] = vect[i];

                prod *= vect[i];

            }

        }

        int[] temp = new int[vect.Length - res_ind];

        Array.Copy(vect, 0, temp, 0, temp.Length);

        return temp;

    }

    public static void Main(String[] args)

    {

        int[] vect = { 3, 5, 7, 2, 2, 5, 7, 7 };

        vect = removeDups(vect);

        for (int i = 0; i

            Console.Write(vect[i] + " ");

    }

}

Поддержка дженериков

Дженерики остаются одной из самых желаемых фич PHP, судя по результатам опроса JetBrains Developer Ecosystem. И тем не менее на данный момент планов их реализовать на уровне языка нет.

В этом релизе мы добавили поддержку нескольких основных сценариев использования дженериков через PHPDoc-аннотации. Этот подход был популяризирован инструментами статического анализа Psalm и PHPStan.

Коллекции и template

Одним из самых популярных применений дженериков являются коллекции. В отличие от обычных массивов такой подход дает меньше ошибок, улучшает подсветку и автодополнение кода.

Вот простейшая реализация коллекции с помощью тега @template:

Для коллекций Doctrine (doctrine/collections) в простых сценариях теперь работает автодополнение:

2021.2 не поддерживает автодополнение элементов в цикле foreach для интерфейса Collection. Этот сценарий уже реализован, но появится в одном из следующих минорных обновлений. Можно подписаться на тикет WI-61438, чтобы получать уведомления.

Поддерживаются только дженерики первого уровня
Это значит, что PhpStorm будет выводить типы и делать автодополнение только для тегов вида Base или Base.

А вот вложенные дженерики вида Base> не поддерживаются, и, скорее всего, не будут поддерживаться в будущем из-за накладных расходов на производительность.

@class-string

Еще одно применение дженериков — фабрики. Они часто принимают строку с именем класса в качестве аргумента и возвращают объект.

Если вы аннотируете параметр тегом @class-string, то PhpStorm предоставит вам соответствующий вывод типа:

Вообще, если вы используете оператор new для инстанцирования объекта из параметра, то можете не добавлять аннотацию @class-string — все будет работать и без нее:

Что дальше?

Планируем постепенно покрыть еще несколько важных сценариев использования дженериков. Например, вот эти:

  • WI-56034 Support the use of generics on classes
  • WI-60894 Support parameter wrapping
  • WI-61497 Generics template @implements should inherit annotations from the interface
  • WI-60895 Infer generic type from constructor

Основной тикет по дженерикам WI-47158 мы закроем, а работу продолжим уже по каждому конкретному кейсу в рамках отдельных тикетах.

Если вы обнаружили не покрытый кейс, создайте, пожалуйста, для него тикет в нашем трекере.

PHP 8.1

Выход новой версии интерпретатора ожидается в конце ноября. А мы по традиции начинаем выкатывать поддержку пораньше.

Одной из самых значимых и ожидаемых фич PHP 8.1, конечно же, будут перечисления (enum).

Перечисления

Объявить перечисление можно ключевыми словами enum и case. Поскольку фича новая и синтаксис может запомниться не сразу, PhpStorm поможет вам автодополнением и подсветит ошибки синтаксиса языка.

Перечисления можно использовать в объявлениях типов (тайпхинтах) параметров, возвращаемых значений и свойств класса.

PhpStorm отследит любые ошибки, связанные с использованием типов, и подсветит их в редакторе.

Новые значения в перечислениях (cases) можно создавать с помощью специального квик-фикса: переставьте указатель туда, куда хотите добавить использование нового кейса, введите его, а затем нажмите Alt+Enter и выберите Add enum case.

Backed enums

По умолчанию кейсы в перечислениях — это простые синглтон-объекты. Но если вы хотите сохранить их в базе данных, то можете определить для них скалярные значения.

Перечисления со скалярными эквивалентами для кейсов, называются backed enums.

Если вы объявили стандартное перечисление (unit enum) и затем решили сделать из него backed enum, то можно нажать Alt+Enter на подчеркнутых кейсах и добавить декларацию типа для всего перечисления.

Кстати, перечисление можно назвать Enum, потому что оно определено как контекстное ключевое слово. И поэтому, если вы использовали какие-либо пакеты с реализацией перечислений через классы, то конфликтов не возникнет — можно переключиться на PHP 8.1 и потом мигрировать.

В перечислениях можно объявлять свои методы, но нельзя объявлять конструкторы, деструкторы и магические методы (кроме __call, __callStatic, и __invoke). Также нельзя объявлять свойства и динамические свойства. Все эти нюансы PhpStorm проверит и, если что не так, подсветит ошибки.

Это все по перечислениям. Будем рады вашим идеям по возможным улучшениям!

Поддержка синтаксиса аrray shape в PHPDoc

Иногда может быть удобнее работать с данными в структурированных ассоциативных массивах. Однако при этом в PhpStorm переставала работать подсветка и автодополнение для ключей и значений.

В этом релизе добавили поддержку PHPDoc-синтаксиса для описания структуры массивов. Это значит, что для ключей будет автодополнение, а для значений определен их тип.

Поддержка работает только для однострочных определений. Многострочные и вложенные определения array shape не поддерживаются.

В качестве альтернативы можно использовать атрибут #[ArrayShape]. Доступен начиная с версии PhpStorm 2020.3 и среди его преимуществ: более красивая подсветка синтаксиса, поддержка многострочности, а также возможность использовать константы для описания структуры.


Улучшенное форматирование кода

Долгое время в PhpStorm были мелкие недоработки по части форматирования. В большинстве случаев оно работало как надо, но недоработки порой могли очень раздражать.

В PhpStorm 2021.2 исправили проблемы с форматированием — теперь оно всегда работает правильно и предсказуемо!

Чтобы отформатировать код, нажмите Ctrl+Alt+L. Вы можете применить форматирование только к выделенному коду либо ко всему файлу сразу.

Все настройки стиля кода доступны в разделе Settings/Preferences | Editor | Code Style | PHP.

Некоторые функции PhpStorm было сложно использовать из-за проблем с форматированием. Например, были проблемы при разделении списков на отдельные строки / объединении их в одну строку. Теперь все будет работать как надо.

Для массивов, списков аргументов и списков параметров теперь можно нажать Alt+Enter и выбрать опцию Split comma-separated values into multiple lines:

Вы можете выбрать способ выравнивания элементов списка. Например, для параметров с тайпхинтами можно выровнять типы и имена по столбцам:

Если вы обнаружите косяк с форматированием, который мы упустили, сразу создайте тикет в нашем баг-трекере.

Новые инспекции и квик-фиксы

В каждом релизе мы добавляем пачку новых инспекций, позволяющих предотвратить возможные баги или оптимизировать код.

Вот некоторые из них.

Условие можно заменить оператором `?->`

Эта проверка находит выражения, которые можно заменить nullsafe-оператором из PHP 8. Нажмите Alt+Enter, чтобы выполнить замену.

Использование константы из класса, в котором она определена

PhpStorm подсветит константы, которые читаются через дочерний класс или интерфейс, а не через тот, где они объявлены. Заменить имя сущности можно нажав Alt+Enter.

Избыточное условие в логическом выражении

Теперь PhpStorm будет проверять все части составных условий, чтобы выявить лишние.

Вот простой пример:

А вот менее очевидный:

Инспекции Refactoring opportunities

Добавили новую группу проверок в Settings/Preferences | Editor | Inspections.

В эту группу входят инспекции, которые помогают находить хорошие кандидаты для рефакторинга. По умолчанию они отключены, но вы все равно будете видеть специальную иконку на полях редактора . Если на нее нажать, вам будет предложен соответствующий рефакторинг.

Вот три примера.

Complex class should be refactored

Эта проверка находит раздутые классы полагаясь на три метрики: мера сцепленности класса (Tight Class Cohesion, TCC), сумма цикломатических сложностей для всех методов в классе (Weighted Method Count, WMC) и количество полей другого класса, к которым обращаются в данном классе (Access To Foreign Data, ATFD).

Когда PhpStorm обнаруживает раздутый класс, он предлагает извлечь методы в новый класс. Если исходный класс слишком велик, может потребоваться еще несколько итераций рефакторинга.

Complex function should be refactored

Эта проверка вычисляет четыре метрики для метода: цикломатическую сложность, глубину вложенности, количество используемых переменных и суммарное количество строк.

Если общая оценка метода низкая, то, вероятно, есть смысл разделить его на более простые, более управляемые части.

PhpStorm предлагает несколько блоков, которые можно извлечь в новый метод.

Method has Feature Envy of another class

Когда метод обращается к данным другого объекта чаще, чем к своим собственным данным, это признак Feature Envy.

Возможно стоит перенести метод или его часть в другой класс.

В группе Refactoring opportunities есть еще несколько инспекций, их описания можно изучить в настройках.

Улучшение рефакторинга Extract Method

Extract Method доступен в PhpStorm с 2011 года и является одним из самых используемых рефакторингов.

Проблема: предположим, у вас слишком большой метод, и вы хотите разбить его на несколько маленьких. Или вы хотите устранить дублирование кода.

Решение: переместить часть кода в новый метод и заменить старый код вызовом метода.

Чтобы использовать этот рефакторинг, выделите фрагмент кода и нажмите Cmd+Alt+M / Ctrl+Alt+M.

Теперь давайте рассмотрим улучшения Extract method в PhpStorm 2021.2.

Рефакторинг для дублирующегося кода

Инспекция Duplicated code fragment позволяет находить повторяющиеся фрагменты кода.

Она была доступна и ранее, но теперь добавили квик-фикс для рефакторинга такого кода.

Инспекция подсветит только первую найденную строку. Поставьте на нее курсор, нажмите Alt+Enter и вызовите Extract Method from duplicate code.

Все повторяющиеся фрагменты будут заменены вызовом нового метода.

Обнаружение дубликатов во время рефакторинга

PhpStorm находит более мелкие дублирующиеся куски в текущем скоупе (метод, класс, файл) непосредственно во время рефакторинга. В версии 2021.2 этот процесс обнаружения стал намного умнее.

Выделите кусок кода и вызовите рефакторинг с помощью ⌘⌥M (Cmd+Alt+M / Ctrl+Alt+M). При обнаружении дубликатов, в нижней части диалога вы увидите чекбокс Review and replace duplicates.

Дубликаты будут найдены, даже если код не полностью идентичен, но схож по сути.

Новый умный селектор для фрагментов кода

Если попытаться вызвать Extract Method, не выделив ничего в редакторе, PhpStorm предложит список фрагментов кода, которые можно извлечь. Это могут быть простые выражения или целые блоки.

PhpStorm не выделит фрагмент кода, если его извлечение недопустимо или бессмысленно. В примере ниже выражение присваивания пропускается — вы можете извлечь только его правую часть.

Улучшение Expand selection

Вы наверняка уже знаете, что можно выделять фрагменты кода с помощью горячей клавиши Expand / Shrink selection ⌥+Up / ⌥+Down (Ctrl+W / Ctrl+Shift+W). Это один из способов быстро выделить код для рефакторинга.

В PhpStorm 2021.2 немного обновили это действие — теперь вы можете выбирать блоки, исключая фигурные скобки.

Автоматическое именование для извлеченных методов

PhpStorm 2021.2 пытается решить одну из самых сложных проблем в компьютерных науках — именование.

Когда вы используете рефакторинг Extract Method, PhpStorm предложит имя для нового метода.

Иногда это будет просто extracted, как и раньше, но в некоторых случаях PhpStorm предложит осмысленные имена на основе используемых переменных.

Если у блока кода есть комментарий, то PhpStorm учтет его при генерации имени для извлеченного метода.

IDE

Действия при сохранении кода

В PhpStorm и раньше позволял настроить действия, срабатывающие при нажатии Cmd+S / Ctrl+S. В этой версии переработали все существующие функции и собрали их в одном месте.

Теперь все опции доступны в разделе Preferences / Settings | Tools | Actions on Save. Перечисленные здесь действия можно включить в перечень действий, вызываемых при нажатии на Cmd+S / Ctrl+S.

Просто установите галочку рядом с названием нужных действий. Большинство действий будет активироваться при любом сохранении, включая автосохранение. Для действий типа "File Watcher" и "Upload to default server" вы можете выбрать один из двух вариантов активации.

Изменение иконки проекта

Добавили небольшую, но приятную фичу, которая поможет улучшить внешний вид проектов на экране приветствия.

Теперь стало проще установить иконки для проектов. Для этого щелкните правой кнопкой мыши на любом проекте и выберите в контекстном меню Choose project icon.

Улучшения scratch-файлов

С помощью scratch-файлов можно делать заметки и писать черновой код вне контекста проекта. Чтобы создать новый scratch-файл, нажмите Ctrl+Shift+N.

В это релизе теперь можно выделить нужный код, нажать Alt+Enter, и выбрать Create new scratch file from selection.

Кроме того, теперь PhpStorm автоматически удаляет пустые файлы, как только вы их закрываете, чтобы помочь вам соблюдать порядок.

Настраиваемый каталог для scratch-файлов

Вы можете настроить папку для хранения scratch-файлов. По умолчанию это каталог конфигурации IDE, но можно указать расшаренную по сети папку и использовать одни и те же scratch-файлы на разных компьютерах.

Для этого необходимо указать опцию командной строки:

-Didea.scratch.path/scratches=

Улучшения в диалоге настроек

В настройках появился новый раздел Advanced Settings. Он содержит некоторые дополнительные параметры конфигурации. Большинство из них были перенесены из Registry.

Там же вы найдете некоторые новые параметры, например, возможность установить отступ слева в режиме Distraction-free mode.

Планируем переносить редко используемые настройки в этот раздел, чтобы сделать основные настройки чище.

Кроме того, теперь можно перемещаться вперед и назад между настройками с помощью стрелок в правом углу окна.


Автоматическая очистка папок с кэшем и логами

Раньше файлы логов и кэша PhpStorm со временем начинали занимать значительное количество места на жестком диске.

Теперь с каждым мажорным обновлением PhpStorm будет автоматически очищать все каталоги кэша и логов, которые не обновлялись более 180 дней.

Можно запустить очистку вручную из главного меню: Help | Delete Leftover IDE Directories....

Быстрый доступ к режиму Power Save

Не секрет, что иногда загрузка CPU при использовании PhpStorm может быть довольно высокой. В основном это происходит во время индексирования. Мы специально используем много ресурсов при индексировании, чтобы максимально ускорить его.

Если вы работаете на ноутбуке без питания и хотите сохранить заряд для нескольких дополнительных часов автономной работы, предлагаем использовать режим Power Save.

Переключиться в режим Power Save можно из статус-бара. Найдите значок батареи или щелкните правой кнопкой мыши в правом нижнем углу статус-бара, и вы найдете опцию Power Save в списке.

Если вы работаете без статус-бара, включить энергосберегающий режим можно в меню File | Power Save Mode.

При включении режима энергосбережения синтаксические ошибки все равно будут подсвечиваться и вам будут доступны все возможности редактора. Но индексирование и некоторые проверки кода, требующие больших затрат CPU, не будут выполняться.

Переключать режим очень легко — вы сможете возвращаться в обычный режим на пару минут, чтобы выполнить нужные проверки, а затем возвращаться в режим энергосбережения.

Если вы заметили какие-либо странности, связанные с загрузкой процессора, сделайте снэпшот процессора и поделитесь им с нашим саппортом.
Вот инструкция о том, как это сделать.

Контроль версий

Единообразное поведение для Show Diff

Теперь вы можете просмотреть дифф изменений файла прямо во вкладке редактора.

Если вам удобнее отслеживать изменения в отдельном окне, вы можете вынести нужный файл в отдельное окно. При этом PhpStorm запомнит, что вы это сделали, и будет открывать последующие диффы в отдельном окне.

GPG-подписи для Git

Теперь можно подписывать Git-коммиты с помощью GPG. Настроить это можно в разделе Preferences/Settings | Version Control | Git.


Текстовый поиск по версиям Local History

Локальная история может выручить, если вы сделали последовательность изменений и не зафиксировали их в системе контроля версий.

Чтобы просмотреть локальную историю файла, щелкните правой кнопкой мыши по названию файла и выберите Local History | Show History.

Теперь в этом окне есть поле поиска, с помощью которого можно найти нужное изменение.


Запуск тестов перед коммитом

PhpStorm и раньше умел автоматически выполнять различные действия перед коммитом.

В PhpStorm 2021.2 появилась еще одна опция — Run Tests.

Нажмите на значок шестеренки в Commit view, выберите опцию Run Tests и выберите нужную Run-конфигурацию из списка. PhpStorm запустит тесты и уведомит вас, если что-то пойдет не так.

Также теперь вы можете настроить параметры для Analyze code и Cleanup. Для этого нажмите кнопку Choose profile рядом с ними.

Вы сможете следить за ходом и результатами проверок в области Commit — PhpStorm не будет отвлекать вас дополнительными модальными окнами.

Code With Me

Code With Me — это инструмент для парного программирования, который поставляется в PhpStorm из коробки. В этом выпуске он был улучшен множеством дополнительных функций и обновлений. Обо всех изменениях можно прочитать в отдельном посте про Code With Me 2021.2.

Демонстрация экрана (Screen Sharing)

Одна из самых желанных фич для Code With Me теперь доступна в 2021.2 — теперь вы можете расшарить окно PhpStorm или весь экран.

Инструменты для работы с БД

PhpStorm включает встроенные возможности DataGrip. Подробнее обо новых возможностях DataGrip читайте в обзоре релиза DataGrip 2021.2 от наших коллег.

C++

#include

using namespace std;

int removeDuplicates(int arr[], int n)

{

    if (n==0 || n==1)

        return n;

    int temp[n];

    int j = 0;

    for (int i=0; i

        if (arr[i] != arr[i+1])

            temp[j++] = arr[i];

    temp[j++] = arr[n-1];

    for (int i=0; i

        arr[i] = temp[i];

    return j;

}

int main()

{

    int arr[] = {1, 2, 2, 3, 4, 4, 4, 5, 5};

    int n = sizeof(arr) / sizeof(arr[0]);

    n = removeDuplicates(arr, n);

    for (int i=0; i

       cout " ";

    return 0;

}

Java

class Main

{

    static int removeDuplicates(int arr[], int n)

    {

        if (n==0 || n==1)

            return n;

        int[] temp = new int[n];

        int j = 0;

        for (int i=0; i1; i++)

            if (arr[i] != arr[i+1])

                temp[j++] = arr[i];

        temp[j++] = arr[n-1];  

        for (int i=0; i

            arr[i] = temp[i];

        return j;

    }

    public static void main (String[] args)

    {

        int arr[] = {1, 2, 2, 3, 4, 4, 4, 5, 5};

        int n = arr.length;

        n = removeDuplicates(arr, n);

        for (int i=0; i

           System.out.print(arr[i]+" ");

    }

}

Python3

def removeDuplicates(arr, n):

    if n == 0 or n == 1:

        return n

    temp = list(range(n))

    j = 0;

    for i in range(0, n-1):

        if arr[i] != arr[i+1]:

            temp[j] = arr[i]

            j += 1

    temp[j] = arr[n-1]

    j += 1

    for i in range(0, j):

        arr[i] = temp[i]

    return j

arr = [1, 2, 2, 3, 4, 4, 4, 5, 5]

n = len(arr)

n = removeDuplicates(arr, n)

for i in range(n):

    print ("%d"%(arr[i]), end = " ")

C#

using System;

class GFG {

    static int removeDuplicates(int []arr, int n)

    {

        if (n == 0 || n == 1)

            return n;

        int []temp = new int[n];

        int j = 0;

        for (int i = 0; i

            if (arr[i] != arr[i+1])

                temp[j++] = arr[i];

        temp[j++] = arr[n-1];

        for (int i = 0; i

            arr[i] = temp[i];

        return j;

    }

    public static void Main ()

    {

        int []arr = {1, 2, 2, 3, 4, 4, 4, 5, 5};

        int n = arr.Length;

        n = removeDuplicates(arr, n);

        for (int i = 0; i

            Console.Write(arr[i] + " ");

    }

}

Javascript

function removeDuplicates(arr, n)

{

    if (n==0 || n==1)

        return n;

    var temp = new Array(n);

    var j = 0;

    for (var i=0; i

        if (arr[i] != arr[i+1])

            temp[j++] = arr[i];

    temp[j++] = arr[n-1];

    for (var i=0; i

        arr[i] = temp[i];

    return j;

}

var arr = [1, 2, 2, 3, 4, 4, 4, 5, 5];

    var n = arr.length;

    n = removeDuplicates(arr, n);

    for (var i=0; i

       document.write( arr[i]+" ");

C++

#include

using namespace std;

int removeDuplicates(int arr[], int n)

{

    if (n==0 || n==1)

        return n;

    int j = 0;

    for (int i=0; i

        if (arr[i] != arr[i+1])

            arr[j++] = arr[i];

    arr[j++] = arr[n-1];

    return j;

}

int main()

{

    int arr[] = {1, 2, 2, 3, 4, 4, 4, 5, 5};

    int n = sizeof(arr) / sizeof(arr[0]);

    n = removeDuplicates(arr, n);

    for (int i=0; i

        cout " ";

    return 0;

}

Java

class Main

{

    static int removeDuplicates(int arr[], int n)

    {

        if (n == 0 || n == 1)

            return n;

        int j = 0;

        for (int i = 0; i 1; i++)

            if (arr[i] != arr[i+1])

                arr[j++] = arr[i];

        arr[j++] = arr[n-1];

        return j;

    }

    public static void main (String[] args)

    {

        int arr[] = {1, 2, 2, 3, 4, 4, 4, 5, 5};

        int n = arr.length;

        n = removeDuplicates(arr, n);

        for (int i=0; i

           System.out.print(arr[i]+" ");

    }

}

Python3 


# Python3 program to remove
# duplicate elements

# This function returns new 
# size of modified array
def removeDuplicates(arr, n):
    if n == 0 or n == 1:
        return n

    # To store index of next
    # unique element
    j = 0

    # Doing same as done
    # in Method 1 Just
    # maintaining another 
    # updated index i.e. j
    for i in range(0, n-1):
        if arr[i] != arr[i+1]:
            arr[j] = arr[i]
            j += 1

    arr[j] = arr[n-1]
    j += 1
    return j

# Driver code
arr = [1, 2, 2, 3, 4, 4, 4, 5, 5]
n = len(arr)

# removeDuplicates() returns
# new size of array.
n = removeDuplicates(arr, n)

# Print updated array
for i in range(0, n):
    print (" %d "%(arr[i]), end = " ")

ADD COLUMN

ADD COLUMN [IF NOT EXISTS] name [type] [default_expr] [codec] [AFTER name_after | FIRST]

Добавляет в таблицу новый столбец с именем name, типом type, кодеком codec и выражением для умолчания default_expr (смотрите раздел Значения по умолчанию).

Если указано IF NOT EXISTS, запрос не будет возвращать ошибку, если столбец уже существует. Если указано AFTER name_after (имя другого столбца), то столбец добавляется (в список столбцов таблицы) после указанного. Если вы хотите добавить столбец в начало таблицы, используйте FIRST. Иначе столбец добавляется в конец таблицы. Для цепочки действий name_after может быть именем столбца, который добавляется в одном из предыдущих действий.

Добавление столбца всего лишь меняет структуру таблицы, и не производит никаких действий с данными - соответствующие данные не появляются на диске после ALTER-а. При чтении из таблицы, если для какого-либо столбца отсутствуют данные, то он заполняется значениями по умолчанию (выполняя выражение по умолчанию, если такое есть, или нулями, пустыми строками). Также, столбец появляется на диске при слиянии кусков данных (см. MergeTree).

Такая схема позволяет добиться мгновенной работы запроса ALTER и отсутствия необходимости увеличивать объём старых данных.

Пример:

ALTER TABLE alter_test ADD COLUMN Added1 UInt32 FIRST;
ALTER TABLE alter_test ADD COLUMN Added2 UInt32 AFTER NestedColumn;
ALTER TABLE alter_test ADD COLUMN Added3 UInt32 AFTER ToDrop;
DESC alter_test FORMAT TSV;
Added1  UInt32
CounterID       UInt32
StartDate       Date
UserID  UInt32
VisitID UInt32
NestedColumn.A  Array(UInt8)
NestedColumn.S  Array(String)
Added2  UInt32
ToDrop  UInt32
Added3  UInt32

DROP COLUMN

DROP COLUMN [IF EXISTS] name

Удаляет столбец с именем name. Если указано IF EXISTS, запрос не будет возвращать ошибку, если столбца не существует.

Запрос удаляет данные из файловой системы. Так как это представляет собой удаление целых файлов, запрос выполняется почти мгновенно.

Пример:

ALTER TABLE visits DROP COLUMN browser

RENAME COLUMN

RENAME COLUMN [IF EXISTS] name to new_name

Переименовывает столбец name в new_name. Если указано выражение IF EXISTS, то запрос не будет возвращать ошибку при условии, что столбец name не существует. Поскольку переименование не затрагивает физические данные колонки, запрос выполняется практически мгновенно.

ЗАМЕЧЕНИЕ: Столбцы, являющиеся частью основного ключа или ключа сортировки (заданные с помощью ORDER BY или PRIMARY KEY), не могут быть переименованы. Попытка переименовать эти слобцы приведет к SQL Error [524].

Пример:

ALTER TABLE visits RENAME COLUMN webBrowser TO browser

CLEAR COLUMN

CLEAR COLUMN [IF EXISTS] name IN PARTITION partition_name

Сбрасывает все значения в столбце для заданной партиции. Если указано IF EXISTS, запрос не будет возвращать ошибку, если столбца не существует.

Как корректно задать имя партиции, см. в разделе Как задавать имя партиции в запросах ALTER.

Пример:

ALTER TABLE visits CLEAR COLUMN browser IN PARTITION tuple()
COMMENT COLUMN [IF EXISTS] name 'Text comment'

Добавляет комментарий к таблице. Если указано IF EXISTS, запрос не будет возвращать ошибку, если столбца не существует.

Каждый столбец может содержать только один комментарий. При выполнении запроса существующий комментарий заменяется на новый.

Посмотреть комментарии можно в столбце comment_expression из запроса DESCRIBE TABLE.

Пример:

ALTER TABLE visits COMMENT COLUMN browser 'Столбец показывает, из каких браузеров пользователи заходили на сайт.'

MODIFY COLUMN

MODIFY COLUMN [IF EXISTS] name [type] [default_expr] [codec] [TTL] [AFTER name_after | FIRST]

Запрос изменяет следующие свойства столбца name:

  • Тип

  • Значение по умолчанию

  • Кодеки сжатия

  • TTL

Примеры изменения кодеков сжатия смотрите в разделе Кодеки сжатия столбцов.

Примеры изменения TTL столбца смотрите в разделе TTL столбца.

Если указано IF EXISTS, запрос не возвращает ошибку при условии, что столбец не существует.

Запрос также может изменять порядок столбцов при помощи FIRST | AFTER, смотрите описание ADD COLUMN.

При изменении типа, значения преобразуются так, как если бы к ним была применена функция toType. Если изменяется только выражение для умолчания, запрос не делает никакой сложной работы и выполняется мгновенно.

Пример запроса:

ALTER TABLE visits MODIFY COLUMN browser Array(String)

Изменение типа столбца - это единственное действие, которое выполняет сложную работу - меняет содержимое файлов с данными. Для больших таблиц, выполнение может занять длительное время.

Выполнение запроса ALTER атомарно.

Запрос ALTER на изменение столбцов реплицируется. Соответствующие инструкции сохраняются в ZooKeeper, и затем каждая реплика их применяет. Все запросы ALTER выполняются в одном и том же порядке. Запрос ждёт выполнения соответствующих действий на всех репликах. Но при этом, запрос на изменение столбцов в реплицируемой таблице можно прервать, и все действия будут осуществлены асинхронно.

MODIFY COLUMN REMOVE

Удаляет какое-либо из свойств столбца: DEFAULT, ALIAS, MATERIALIZED, CODEC, COMMENT, TTL.

Синтаксис:

ALTER TABLE table_name MODIFY column_name REMOVE property;

Пример

Удаление свойства TTL:

ALTER TABLE table_with_ttl MODIFY COLUMN column_ttl REMOVE TTL;

Смотрите также

  • REMOVE TTL.

CPP

#include

using namespace std;

void removeDuplicates(char* S)

{

    if (S[0] == '\0')

        return;

    if (S[0] == S[1]) {

        int i = 0;

        while (S[i] != '\0') {

            S[i] = S[i + 1];

            i++;

        }

        removeDuplicates(S);

    }

    removeDuplicates(S + 1);

}

int main()

{

    char S1[] = "geeksforgeeks";

    removeDuplicates(S1);

    cout

    char S2[] = "aabcca";

    removeDuplicates(S2);

    cout

    return 0;

}

Java

import java.io.*;

class GFG {

    public static String removeConsecutiveDuplicates(String input) {

        if(input.length()1)

            return input;

        if(input.charAt(0)==input.charAt(1))

            return removeConsecutiveDuplicates(input.substring(1));

        else

            return input.charAt(0) + removeConsecutiveDuplicates(input.substring(1));

    }

    public static void main(String[] args)

    {

        String S1 = "geeksforgeeks";

        System.out.println(removeConsecutiveDuplicates(S1));

        String S2 = "aabcca";

        System.out.println(removeConsecutiveDuplicates(S2));

    }

}

Javascript

function removeConsecutiveDuplicates(input)

{

    if(input.length

            return input;

        if(input[0]==input[1])

            return removeConsecutiveDuplicates(input.substring(1));

        else

            return input[0] +

            removeConsecutiveDuplicates(input.substring(1));

}

let S1 = "geeksforgeeks";

document.write(removeConsecutiveDuplicates(S1)+"
"
);

let  S2 = "aabcca";

document.write(removeConsecutiveDuplicates(S2)+"
"
);

C++

#include

using namespace std;

void removeDuplicates(char S[]){

   int n = strlen(S);

   if (n

     return;

   int j = 0;

   for (int i=1; i

   {

       if (S[j] != S[i])

       {

           j++;

           S[j] = S[i];

       }    

   }  

   j++;

   S[j] = '\0';    

}

int main() {

    char S1[] = "geeksforgeeks";

    removeDuplicates(S1);

    cout

    char S2[] = "aabcca";

    removeDuplicates(S2);

    cout

    return 0;

}

Java

import java.util.*;

class GFG

{

    static void removeDuplicates(char[] S)

    {

        int n = S.length;

        if (n 2)

        {

            return;

        }

        int j = 0;

        for (int i = 1; i

        {

            if (S[j] != S[i])

            {

                j++;

                S[j] = S[i];

            }

        }

        System.out.println(Arrays.copyOfRange(S, 0, j + 1));

    }

    public static void main(String[] args)

    {

        char S1[] = "geeksforgeeks".toCharArray();

        removeDuplicates(S1);

        char S2[] = "aabcca".toCharArray();

        removeDuplicates(S2);

    }

}

Python3

def removeDuplicates(S):

    n = len(S)

    if (n 2) :

        return

    j = 0

    for i in range(n):

        if (S[j] != S[i]):

            j += 1

            S[j] = S[i]

    j += 1

    S = S[:j]

    return S

if __name__ == '__main__':

    S1 = "geeksforgeeks"

    S1 = list(S1.rstrip())

    S1 = removeDuplicates(S1)

    print(*S1, sep = "")

    S2 = "aabcca"

    S2 = list(S2.rstrip())

    S2 = removeDuplicates(S2)

    print(*S2, sep = "")

Introduction

Orchid is a free Laravel package that abstracts standard business logic and allows code-driven rapid application development of back office applications, admin/user panels and dashboards.

Laravel Orchid Platform

Interesting Features

  • Rapid Application Development - Focus to PHP development and don't lose time with HTML, CSS, or JavaScript. Build application logic, not admin panels. Try our quick start guide and kick-start your application's development.

  • Form Builder - Prevent reinventing the wheel or forms. Orchid supports already 40+ form elements "out of the box" and allows you to build all kinds of forms quickly.

  • Fast Loading Times - Enjoy a SPA like performance! Transitions can be made without reloading a page and require no additional code. Thanks to the Hotwire project, Orchid makes this a satisfying experience for you and your users.

  • Access Permissions & Roles - Take advantage of granular access permissions, based on a user’s identity and corresponding role membership.

  • Filtering & Sorting - Offer your users the ability to filter and sort data quickly! Orchid uses an Eloquent based filtering/sorting approach.

  • Fast Full-Text Search - Take advantage of the integrated Laravel Scout based full-text search, that allows searching through all available content, and displaying search results almost instantly.

  • Multiple Notifications Types - Orchid offers various types of notifications and allows your application to keep your users informed appropriately.

Live Demo

Curious but not (yet) in the mood to read the documentation? Click here, to experience a live demo of Orchid.

Getting started

Documentation

  • 🌍 Documentation & Quick Start Guide
  • 🇷🇺 Чтобы ознакомиться с руководством, посетите сайт orchid.software

Blog

Orchid's blog informs about news and announcements around Laravel Orchid, including related projects.

Feedback/Support

We are continually trying to actively include feedback from the community in the development of Orchid. You help us a lot if you give us well structured and detailed feedback.

GitHub

  • Create issues to ask questions or report problems.
  • Participate in disccussions around Orchid and share your ideas/opinions.

Telegram User Groups

  • Global Community
  • Russian Community
  • Spanish Community

Development

Releasese Strategy

We like to keep things as modern as possible and have a "release early, release often" approach to major releases. Meaning, we won't wait an arbitrary number of months to accumulate significant changes and release the next major version. By releasing major versions often, new features will be out earlier, and upgrading between versions will be much easier.

Changelog

We actively and continuously maintain a changelog that informs about Orchid's history of improvements, bug fixes and changes.

Support Orchid

Thanks to our backers 🙏 , Orchid is free for private and commercial purposes. 🎉

Voluntary donations are allowing us to spend more time improving Orchid for everyone! 👍

Полная очистка текста от html-тегов

Часто для таких задач используются регулярные выражения, однако в этой статье рассмотрим самый простой метод – удаление тегов с помощью php-функции strip_tags. Эта функция просто удаляет теги из указанной в параметре строки.

$str_in = "

Мой текст с различными тегами.

" ;
$str_out = strip_tags($str_in);
echo $str_out;

В результате такой обработки в переменной $str_out получим строку без тегов:

Мой текст с различными тегами.

* Стоит обратить внимание, что функция strip_tags убирает только сами теги, оставляя их содержимое между открывающим и закрывающим тегом.

Удаление отдельных html-тегов из текста

Иногда нужно убрать только определенные теги из строки. Здесь мы так же воспользуемся функцией strip_tags, но в этот раз вторым (необязательным) параметром укажем теги, которые нужно сохранить.

Например, при обработке строки, нужно оставить только ссылки:

$str_in = "

Мой текст с различными тегами.

" ;
$str_out = strip_tags($str_in, "" );
echo $str_out;

В результате такой обработки в переменной $str_out получим:

Мой текст с различными тегами.

Таким образом, можно указать все теги, которые допустимы в строке, тогда как все остальные будут удалены.

В данной статье рассмотрен самый простой способ очистки строки от тегов. Рассматривая другие варианты, я буду расширять эту статью. Буду рад, если Вы предложите свои варианты решения этой задачи в комментариях или по электронной почте.

Когда вы принимаете данные от пользователей, через ту же , есть смысл обрабатывать передаваемые от них данные и получать на выходе чистый текст.

Как это можно сделать разными способами, я сейчас расскажу.

Как удалить все HTML-теги из строки на PHP?

В PHP существует функция под названием «strip_tags ». С помощью нее можно быстро и просто удалить все HTML- теги из переменной.

Реализация:

Hello, world!"; $content = strip_tags($content); echo $content; // Выведет "Hello, world!" ?>

Hello, world!

"; $content = strip_tags($content, "

"); echo $content; // Выведет "Hello, world!

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Vivamus sed lacus vel diam consectetur rhoncus et eget justo.

" ?>

В таком случае мы сохраняем теги

И . У тегов, имеющих закрывающий тег, прописывать при сохранении его не нужно.

Обратите внимание , функция не проверяет HTML-разметку на валидность, и если есть незакрытые теги, то вы рискуете потерять обычный текст.

Как удалить все HTML-теги из строки на JavaScript?

В JavaScript мы напишем свою небольшую функцию, с помощью которой в последующем и будем обрабатывать полученные данные.

Реализация:

Этот пример работает на конкретной заданной переменной, вы же можете переделать его под полученное содержимое, например, из поля input.

С задачей очистки html от лишних тегов сталкиваются абсолютно все.

Первое, что приходит на ум, это использовать php-функцию strip_tags():
string strip_tags (string str [, string allowable_tags])

Функция возвращает строку, очищенную от тегов. В качестве аргумента allowable_tags передаются теги, которые не надо удалять . Функция работает, но, мягко говоря, неидеально. По ходу, там нет проверки на валидность кода, что может повлечь за собой удаление текста, не входящего в тэги.
Инициативные разработчики сложа руки не сидели — в сети можно найти доработанные функции. Хорошим примером является strip_tags_smart .

Применять или не применять готовые решения — личный выбор программиста. Так сложилось, что мне чаще всего не требуется "универсального" обработчика и бывает удобнее почистить код регулярками.

От чего зависит выбор того или иного способа обработки?

1. От исходного материала и сложности его анализа.
Если вам нужно обрабатывать достаточно простые htmp-тексты, без какой-либо навороченной верстки, ясные, как день:), то можно использовать стандартные функции.
Если в текстах есть определенные особенности, которые надо учесть, то тут-то и пишутся специальные обработчики. В одних может использоваться просто str_replace . Например:

$s = array("’" => "’", // Right-apostrophe (eg in I"m)
"“" => "“", // Opening speech mark
"–" => "—", // Long dash
"â€" => "”", // Closing speech mark
"Ã " => "é", // e acute accent
chr(226) . chr(128) . chr(153) => "’", // Right-apostrophe again
chr(226) . chr(128) . chr(147) => "—", // Long dash again
chr(226) . chr(128) . chr(156) => "“", // Opening speech mark
chr(226) . chr(128) . chr(148) => "—", // M dash again
chr(226) . chr(128) => "”", // Right speech mark
chr(195) . chr(169) => "é", // e acute again
);

foreach ($s as $needle => $replace)
{
$htmlText = str_replace($needle, $replace, $htmlText);
}

Другие могут быть основаны на регулярных выражениях . Как пример:

Function getTextFromHTML($htmlText)
{
$search = array ("""si", // Remove javaScript
"""si", // Remove styles
""]*?>.*?"si", // Remove xml tags
""]*?>"si", // Remove HTML-tags
""([\r\n])[\s] "", // Remove spaces
""&(quot|#34);"i", // Replace HTML special chars
""&(amp|#38);"i",
""&(lt|#60);"i",
""&(gt|#62);"i",
""&(nbsp|#160);"i",
""&(iexcl|#161);"i",
""&(cent|#162);"i",
""&(pound|#163);"i",
""&(copy|#169);"i",
""(\d);"e"); // write as php

$replace = array ("",
"",
"",
"",
"\\1",
"\"",
"&",
" ">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");

Return preg_replace($search, $replace, $htmlText);
}
(В такие минуты как никогда радует возможность preg_replace работать с массивами в качестве параметров). Массив вы при необходимости дополняете своими регулярками. Помочь в их составлении вам может, например, этот конструктор регулярных выражений . Начинающим разработчикам может быть полезной статья "All about HTML tags. 9 Regular Expressions to strip HTML tags" . Посмотрите там примеры, проанализируйте логику.

2. От объемов.
Объемы напрямую связаны со сложностью анализа (из предыдущего пункта). Большое количество текстов увеличивает вероятность, что, пытаясь предусмотреть и почистить все регулярками, вы можете что-нибудь да упустить. В этом случае подойдет метод "многоступенчатой" очистки. То есть очистить сначала, допустим, функцией strip_tags_smart (исходники на всякий случай не удаляем). Потом выборочно просматриваем некоторое количество текстов на выявление "аномалий". Ну и "зачищаем" аномалии регулярками.

3. От того, что надо получить в результате.
Алгоритм обработки может быть упрощен разными способами в зависимости от ситуации. Случай, описанный мной в одной из предыдущих статей , хорошо это демонстрирует. Напомню, текст там находился в div-е, в котором кроме него был еще div с "хлебными крошками", реклама адсенс, список похожих статей. При анализе выборки статей обнаружилось, что статьи не содержат рисунков и просто разбиты на абзацы с помощью . Чтобы не чистить "главный" див от посторонних вещей, можно найти все абзацы (с Simple HTML DOM Parser это очень просто) и соединить их содержимое. Так что прежде чем составлять регулярки для чистки, посмотрите, нельзя ли обойтись малой кровью.

Вообще, между сторонниками парсинга html-кода, основанного чисто на регулярных выражениях, и парсинга, в основе которого лежит анализ DOM-структуры документа, в сети разгораются настоящие холивары. Вот, например, на оверфлоу. Невинный с первого взгляда

У Вас в браузере заблокирован JavaScript. Разрешите JavaScript для работы сайта!

(PHP 3 >= 3.0.8, PHP 4, PHP 5)

strip_tags - Удаляет HTML и PHP тэги из строки

Using PHP unset() Function

Use the PHP unset() function to delete an element from an array.

Basically it is used to unset any variable in PHP. This function accept variable as argument and unset it.

Example:

  $arr = array("a" => "apple", "b" => "ball", "c" => "cat");

  unset($arr["b"]);

?>

Output:

array("a" => "Apple", "c" => "Cat")

Another Example:

  $arr = array(1, 2, 3, 4, 5);

  unset($arr[3]);

  print_r($arr)

?>

Output:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [4] => 5
)

You can see the result array is not indexed. To overcome from this condition, you can use array_splice() PHP function described below.

Using PHP array_splice() Function

You can also use array_splice() function to remove specific array element. This function also can be used to replace array elements by passing array with update values.

This function takes three parameters, an array, offset (where to start), and length (number of elements to be removed).

Here is an example with array_splice() function:

  $arr = array(1, 2, 3, 4, 5);

  array_splice($arr, 2, 2);

  print_r($arr)

?>

Output:

Array
(
    [0] => 1
    [1] => 2
    [2] => 5
)

You can see that the result array is re-indexed.