Как использовать str_split с регулярным выражением в R?

У меня есть такая строка:

235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things

Я хочу разбить строку на 6-значные числа. Т.е. - Я хочу этот:

235072,testing,some2wg2f4,wf484-things
224072,and,other25wg4,14-thingies
223552,testing,some/2wr24,14084-things

Как мне это сделать с помощью регулярного выражения? Следующее не работает (с использованием пакета stringr):

> blahblah <- "235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things"
> test <- str_split(blahblah, "([0-9]{6}.*)")
> test
[[1]]
[1] "" ""

Что мне не хватает?

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

Marius 23.03.2018 00:01

Спасибо! Это устранило проблему. Однако я только что понял, что у меня есть какие-то 7-значные числа, которые все портят. У вас есть способ исключить 7-значные числа, но продолжить синтаксический анализ по 6-значным ??

lukehawk 23.03.2018 00:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
1 012
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вот подход с базой R, использующий позитивный просмотр вперед и назад, и спасибо @thelatemail за исправление:

strsplit(x, "(?<=.)(?=[0-9]{6})", perl = TRUE)[[1]]
# [1] "235072,testing,some252f4,14084-things"  
# [2] "224072,and,other2524,14084-thingies"    
# [3] "223552,testing,some/2wr24,14084-things"

Спасибо! Черт возьми, я ненавижу регулярное выражение. Вы рекомендуете какие-нибудь хорошие вступления ?? Каждый раз, когда я думаю, что понимаю, я оказываюсь здесь ...

lukehawk 23.03.2018 00:04

Ваше решение обрезает последний символ первых двух строк. Почему так?

lukehawk 23.03.2018 00:08

@lukehawk, проблема в том, что эти последние символы использовались для разделения. Что касается вступлений, я не уверен ... Практика и ответы на вопросы здесь работают хорошо.

Julius Vainora 23.03.2018 00:15

@lukehawk, для вашей новой проблемы попробуйте strsplit(x, "(?<=\\D)(?=[0-9]{6}\\D)", perl = TRUE)[[1]].

Julius Vainora 23.03.2018 00:18

Спасибо, Юлиус - я не знал, что это будет иметь значение, но эта строка очень большая, около 50 МБ. Я переключился на решение str_extract_all, так как оно, кажется, гораздо лучше справляется с большой строкой.

lukehawk 23.03.2018 01:06
Ответ принят как подходящий

Альтернативный подход с str_extract_all. Обратите внимание: я использовал .*? для «нежадного» сопоставления, иначе .* расширяется, чтобы захватить все:

> str_extract_all(blahblah, "[0-9]{6}.*?(?=[0-9]{6}|$)")[[1]]
[1] "235072,testing,some252f4,14084-things"  "224072,and,other2524,14084-thingies"    "223552,testing,some/2wr24,14084-things"

Я действительно использовал это решение, так как оно, кажется, работает намного лучше с моей очень большой строкой (49 МБ). Однако как мне теперь настроить его, чтобы он принимал в качестве разделителей 6- или 3-значные (но не любые другие суммы) целые числа?

lukehawk 23.03.2018 00:55

Это работает с str_extract_all(mystring, "[0-9]*.*?(?=\\s{5}[0-9]{3}|\\s{5}[0-9]{6}|$)"), но он добавляет пустую строку после каждой реальной строки, поэтому я получаю вдвое больше результатов. Есть идеи, почему?

lukehawk 23.03.2018 01:02

ПОНЯТНО! Это отлично работает - str_extract_all(mystring, "(\\d{6}|\\d{3}).*?(?=\\s{5}[0-9]{3}|\\s{5}[0-9]{6}|$)")[[1]‌​] Спасибо за помощь!

lukehawk 23.03.2018 01:09

Я думаю, поскольку у вас есть только * («ноль или более») и опережающие просмотры в этом, это позволяет совпадение нулевой длины в точке, где совпадает опережающий просмотр. Хотя в комментариях сложно разобраться с этим, возможно, лучше было бы написать новый вопрос с четкими примерами новой проблемы (все будет в порядке, если у вас есть хорошие примеры, поясняющие, чем он отличается от этой).

Marius 23.03.2018 01:10

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

library(stringr)
library(magrittr)

str <- "235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things"

out <- 
    str_replace_all(str, "(\\d{6})", "#SPLIT_HERE#\\1") %>% 
    str_split("#SPLIT_HERE#") %>% 
    unlist

[1] ""                                       "235072,testing,some252f4,14084-things" 
[3] "224072,and,other2524,14084-thingies"    "223552,testing,some/2wr24,14084-things"

Если совпадение происходит в начале или в конце строки, str_split() вставит пустые символы в вектор результатов, чтобы указать это (как это было выше). Если вам не нужна эта информация, вы можете легко удалить ее с помощью out[nchar(out) != 0].

[1] "235072,testing,some252f4,14084-things"  "224072,and,other2524,14084-thingies"   
[3] "223552,testing,some/2wr24,14084-things"

С менее сложным регулярным выражением вы можете сделать следующее:

s <- "235072,testing,some252f4,14084-things224072,and,other2524,14084-thingies223552,testing,some/2wr24,14084-things"
l <- str_locate_all(string = s, "[0-9]{6}")
str_sub(string = s, start = as.data.frame(l)$start, 
    end = c(tail(as.data.frame(l)$start, -1) - 1, nchar(s)) )
# [1] "235072,testing,some252f4,14084-things"
# [2] "224072,and,other2524,14084-thingies"
# [3] "223552,testing,some/2wr24,14084-things"

Другие вопросы по теме