Как может я строки замены в тексте в Java?

Я полагаю, что ваш вопрос касается нормализации различий между последовательностями. Например, Sabherwal и Robey (1993, стр. 557) ссылаются на стандартизацию расстояний, предложенную Abbott & amp; Hyrcac (1990) и вообще не рассматривают стандартизацию последовательности. Во всяком случае, я не могу понять, какой может быть стандартизация последовательности.

Функция seqdist в TraMineR имеет аргумент norm, который можно использовать для нормализации некоторых из предложенных мер расстояния. Вот выдержка из справочной страницы seqdist:

Расстояния могут быть дополнительно нормализованы с помощью аргумента норма. Если установлено значение «auto», нормализация Эльзинга (сходство, деленное на среднее геометрическое двух длин последовательностей) применяется к расстояниям «LCS», «LCP» и «RLCP», в то время как нормализация Эбботта (расстояние делится на длину более длинной последовательности) используется для «OM», «HAM» и «DHD». Метод Эльзинга можно принудить с помощью «gmean», а правило Эбботта - с «maxlength». С помощью «maxdist» расстояние нормализуется по максимально возможному значению. Для получения более подробной информации см. Gabadinho et al. (2009, 2011). Наконец, YujianBo - это нормализация, предложенная Yujian и Bo (2007), которая сохраняет неравенство треугольника.

blockquote>

Позвольте мне предупредить вас, что, хотя нормализация делает расстояния между двумя короткими последовательностями (скажем, длиной 10) более сопоставимыми с расстояниями между двумя длинными последовательностями (скажем, длиной 100), она не решает проблему сравнения последовательностей. разной длины.

Подробное обсуждение нормализации расстояния и сходства в анализе последовательностей можно найти в Elzinga & amp; Studer (2016) .

5
задан szabgab 20 December 2008 в 09:23
поделиться

4 ответа

Я должен был на самом деле использовать этот вид алгоритма несколько раз за прошлые две недели. Таким образом, здесь это - второй больше всего подробный язык в мире...

import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

/*
R1  => R2
R2  => R3
R3  => R1
R12 => R21
R21 => R12
*/

String inputString 
    = "mv A, R3\n"
    + "mv R2, B\n"
    + "mv R1, R3\n"
    + "mv B, R4\n"
    + "add A, R1\n"
    + "add B, R1\n"
    + "add R1, R2\n"
    + "add R3, R3\n"
    + "add R21, X\n"
    + "add R12, Y\n"
    + "mv X, R2"
    ;

System.out.println( "inputString = \"" + inputString + "\"" );

HashMap h = new HashMap();
h.put( "R1",  "R2" );
h.put( "R2",  "R3" );
h.put( "R3",  "R1" );
h.put( "R12", "R21" );
h.put( "R21", "R12" );

Pattern      p       = Pattern.compile( "\\b(R(?:12?|21?|3))\\b");
Matcher      m       = p.matcher( inputString );
StringBuffer sbuff   = new StringBuffer();
int          lastEnd = 0;
while ( m.find()) {
    int mstart = m.start();
    if ( lastEnd < mstart ) { 
        sbuff.append( inputString.substring( lastEnd, mstart ));
    }
    String key   = m.group( 1 );
    String value = (String)h.get( key );
    sbuff.append( value );
    lastEnd = m.end();
}
if ( lastEnd < inputString.length() ) { 
    sbuff.append( inputString.substring( lastEnd ));
}

System.out.println( "sbuff = \"" + sbuff + "\"" );

Это может быть Java-ified этими классами:

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

interface StringReplacer { 
    public CharSequence getReplacement( Matcher matcher );
}

class Replacementifier { 

    static Comparator keyComparator = new Comparator() { 
         public int compare( Object o1, Object o2 ) {
             String s1   = (String)o1;
             String s2   = (String)o2;
             int    diff = s1.length() - s2.length();
             return diff != 0 ? diff : s1.compareTo( s2 );
         }
    };
    Map replaceMap = null;

    public Replacementifier( Map aMap ) { 
        if ( aMap != null ) { 
            setReplacements( aMap ); 
        }
    }

    public setReplacements( Map aMap ) { 
        replaceMap = aMap;
    }

    private static String createKeyExpression( Map m ) { 
        Set          set = new TreeSet( keyComparator );
        set.addAll( m.keySet());
        Iterator     sit = set.iterator();
        StringBuffer sb  = new StringBuffer( "(" + sit.next());

        while ( sit.hasNext()) { 
            sb.append( "|" ).append( sit.next());
        }
        sb.append( ")" );
        return sb.toString();
    }

    public String replace( Pattern pattern, CharSequence input, StringReplacer replaceFilter ) {
        StringBuffer output  = new StringBuffer();
        Matcher      matcher = pattern.matcher( inputString );
        int          lastEnd = 0;
        while ( matcher.find()) {
            int mstart = matcher.start();
            if ( lastEnd < mstart ) { 
                output.append( inputString.substring( lastEnd, mstart ));
            }
            CharSequence cs = replaceFilter.getReplacement( matcher );
            if ( cs != null ) { 
                output.append( cs );
            }
            lastEnd = matcher.end();
        }
        if ( lastEnd < inputString.length() ) { 
            sbuff.append( inputString.substring( lastEnd ));
        }
    }

    public String replace( Map rMap, CharSequence input ) {
        // pre-condition
        if ( rMap == null && replaceMap == null ) return input;

        Map     repMap = rMap != null ? rMap : replaceMap;
        Pattern pattern  
            = Pattern.compile( createKeyExpression( repMap ))
            ;
        StringReplacer replacer = new StringReplacer() { 
            public CharSequence getReplacement( Matcher matcher ) {
                String key   = matcher.group( 1 );
                return (String)repMap.get( key );
            }
        };
        return replace( pattern, input, replacer ); 
    }
}
5
ответ дан 14 December 2019 в 19:28
поделиться

Решение для жемчуга имеет преимущество замены всех строк в одном выстреле, виде "транзакционно". Если у Вас нет той же опции в Java (и я не могу думать о пути, заставляют его произойти), необходимо остерегаться замены R1 => R2, то R2 => R3. В этом случае и R1 и R2 заканчивают тем, что были заменены R3.

2
ответ дан 14 December 2019 в 19:28
поделиться

Вот менее подробный способ сделать это в одной передаче, с помощью API Matcher низшего уровня: appendReplacement() и appendTail().

import java.util.*;
import java.util.regex.*;

public class Test
{
  public static void main(String[] args) throws Exception
  {
    String inputString 
      = "mv A, R3\n"
      + "mv R2, B\n"
      + "mv R1, R3\n"
      + "mv B, R4\n"
      + "add A, R1\n"
      + "add B, R1\n"
      + "add R1, R2\n"
      + "add R3, R3\n"
      + "add R21, X\n"
      + "add R12, Y\n"
      + "mv X, R2"
      ;

      System.out.println(inputString);
      System.out.println();
      System.out.println(doReplace(inputString));
  }

  public static String doReplace(String str)
  {
     Map<String, String> map = new HashMap<String, String>()
     {{
        put("R1", "R2");
        put("R2", "R3");
        put("R3", "R1");
        put("R12", "R21");
        put("R21", "R12");
     }};

     Pattern p = Pattern.compile("\\bR\\d\\d?\\b");
     Matcher m = p.matcher(str);
     StringBuffer sb = new StringBuffer();
     while (m.find())
     {
       String repl = map.get(m.group());
       if (repl != null) 
       {
         m.appendReplacement(sb, "");
         sb.append(repl);
       }
     }
     m.appendTail(sb);
     return sb.toString();
  }
}

Отметьте это appendReplacement() обрабатывает замещающую строку для замены последовательностей $n текстом от групп получения, которые мы не хотим в этом случае. Чтобы избежать, чтобы, я передал его пустая строка, затем используют StringBuffer append() метод вместо этого.

Elliott Hughes опубликовал предварительно упакованную реализацию этой техники здесь. (Он склонен добавлять ссылки на другие служебные классы, которые он записан, таким образом, можно хотеть удалить тесты в его main() метод перед компиляцией его.)

0
ответ дан 14 December 2019 в 19:28
поделиться

Можно использовать HashMap:

Map<String, String> map = new HashMap<String, String>();
map.put("R1", "R2");
map.put("R2", "R3");

for(String key: map.keySet()) {
  str.replaceAll(key, map.get(key));
}

replaceAll также обрабатывает регулярные выражения.

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

public class Replacement {

    private String newS;
    private String old;

    public Replacement(String old, String newS) {
        this.newS = newS;
        this.old = old;
    }

    public String getOld() {
        return old;
    }

    public String getNew() {
        return newS;
    }
}

SortedMap<Integer, Replacement> map = new TreeMap<Integer, Replacement>();

map.put(new Integer(1), new Replacement("R2", "R3"));
map.put(new Integer(2), new Replacement("R1", "R2"));

for(Integer key: map.keySet()) {
   str.replaceAll(map.get(key).getOld(), map.get(key).getNew());
}

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

R1 -> R2
R2 -> R3
R3 -> R1

Необходимо использовать некоторые 'временные' переменные для них:

R1 -> R@1
R2 -> R@3
R3 -> R1
R@(\d{1}) -> R\1

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

-2
ответ дан 14 December 2019 в 19:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: